@@ -163,15 +163,31 @@ void disk_flush_events(struct gendisk *disk, unsigned int mask)
163
163
spin_unlock_irq (& ev -> lock );
164
164
}
165
165
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
+
166
184
static void disk_check_events (struct disk_events * ev ,
167
185
unsigned int * clearing_ptr )
168
186
{
169
187
struct gendisk * disk = ev -> disk ;
170
- char * envp [ARRAY_SIZE (disk_uevents ) + 1 ] = { };
171
188
unsigned int clearing = * clearing_ptr ;
172
189
unsigned int events ;
173
190
unsigned long intv ;
174
- int nr_events = 0 , i ;
175
191
176
192
/* check events */
177
193
events = disk -> fops -> check_events (disk , clearing );
@@ -193,19 +209,8 @@ static void disk_check_events(struct disk_events *ev,
193
209
if (events & DISK_EVENT_MEDIA_CHANGE )
194
210
inc_diskseq (disk );
195
211
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 );
209
214
}
210
215
211
216
/**
@@ -284,6 +289,32 @@ bool bdev_check_media_change(struct block_device *bdev)
284
289
}
285
290
EXPORT_SYMBOL (bdev_check_media_change );
286
291
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
+
287
318
/*
288
319
* Separate this part out so that a different pointer for clearing_ptr can be
289
320
* passed in for disk_clear_events.
0 commit comments