@@ -163,15 +163,31 @@ void disk_flush_events(struct gendisk *disk, unsigned int mask)
163163 spin_unlock_irq (& ev -> lock );
164164}
165165
166+ /*
167+ * Tell userland about new events. Only the events listed in @disk->events are
168+ * reported, and only if DISK_EVENT_FLAG_UEVENT is set. Otherwise, events are
169+ * processed internally but never get reported to userland.
170+ */
171+ static void disk_event_uevent (struct gendisk * disk , unsigned int events )
172+ {
173+ char * envp [ARRAY_SIZE (disk_uevents ) + 1 ] = { };
174+ int nr_events = 0 , i ;
175+
176+ for (i = 0 ; i < ARRAY_SIZE (disk_uevents ); i ++ )
177+ if (events & disk -> events & (1 << i ))
178+ envp [nr_events ++ ] = disk_uevents [i ];
179+
180+ if (nr_events )
181+ kobject_uevent_env (& disk_to_dev (disk )-> kobj , KOBJ_CHANGE , envp );
182+ }
183+
166184static void disk_check_events (struct disk_events * ev ,
167185 unsigned int * clearing_ptr )
168186{
169187 struct gendisk * disk = ev -> disk ;
170- char * envp [ARRAY_SIZE (disk_uevents ) + 1 ] = { };
171188 unsigned int clearing = * clearing_ptr ;
172189 unsigned int events ;
173190 unsigned long intv ;
174- int nr_events = 0 , i ;
175191
176192 /* check events */
177193 events = disk -> fops -> check_events (disk , clearing );
@@ -193,19 +209,8 @@ static void disk_check_events(struct disk_events *ev,
193209 if (events & DISK_EVENT_MEDIA_CHANGE )
194210 inc_diskseq (disk );
195211
196- /*
197- * Tell userland about new events. Only the events listed in
198- * @disk->events are reported, and only if DISK_EVENT_FLAG_UEVENT
199- * is set. Otherwise, events are processed internally but never
200- * get reported to userland.
201- */
202- for (i = 0 ; i < ARRAY_SIZE (disk_uevents ); i ++ )
203- if ((events & disk -> events & (1 << i )) &&
204- (disk -> event_flags & DISK_EVENT_FLAG_UEVENT ))
205- envp [nr_events ++ ] = disk_uevents [i ];
206-
207- if (nr_events )
208- kobject_uevent_env (& disk_to_dev (disk )-> kobj , KOBJ_CHANGE , envp );
212+ if (disk -> event_flags & DISK_EVENT_FLAG_UEVENT )
213+ disk_event_uevent (disk , events );
209214}
210215
211216/**
@@ -284,6 +289,32 @@ bool bdev_check_media_change(struct block_device *bdev)
284289}
285290EXPORT_SYMBOL (bdev_check_media_change );
286291
292+ /**
293+ * disk_force_media_change - force a media change event
294+ * @disk: the disk which will raise the event
295+ * @events: the events to raise
296+ *
297+ * Generate uevents for the disk. If DISK_EVENT_MEDIA_CHANGE is present,
298+ * attempt to free all dentries and inodes and invalidates all block
299+ * device page cache entries in that case.
300+ *
301+ * Returns %true if DISK_EVENT_MEDIA_CHANGE was raised, or %false if not.
302+ */
303+ bool disk_force_media_change (struct gendisk * disk , unsigned int events )
304+ {
305+ disk_event_uevent (disk , events );
306+
307+ if (!(events & DISK_EVENT_MEDIA_CHANGE ))
308+ return false;
309+
310+ if (__invalidate_device (disk -> part0 , true))
311+ pr_warn ("VFS: busy inodes on changed media %s\n" ,
312+ disk -> disk_name );
313+ set_bit (GD_NEED_PART_SCAN , & disk -> state );
314+ return true;
315+ }
316+ EXPORT_SYMBOL_GPL (disk_force_media_change );
317+
287318/*
288319 * Separate this part out so that a different pointer for clearing_ptr can be
289320 * passed in for disk_clear_events.
0 commit comments