VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   33 Branches   57 Tags
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200   1) // SPDX-License-Identifier: GPL-2.0
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200   2) /*
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200   3)  * Disk events - monitor disk events like media change and eject request.
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200   4)  */
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200   5) #include <linux/export.h>
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200   6) #include <linux/moduleparam.h>
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200   7) #include <linux/genhd.h>
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200   8) #include "blk.h"
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200   9) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  10) struct disk_events {
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  11) 	struct list_head	node;		/* all disk_event's */
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  12) 	struct gendisk		*disk;		/* the associated disk */
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  13) 	spinlock_t		lock;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  14) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  15) 	struct mutex		block_mutex;	/* protects blocking */
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  16) 	int			block;		/* event blocking depth */
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  17) 	unsigned int		pending;	/* events already sent out */
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  18) 	unsigned int		clearing;	/* events being cleared */
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  19) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  20) 	long			poll_msecs;	/* interval, -1 for default */
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  21) 	struct delayed_work	dwork;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  22) };
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  23) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  24) static const char *disk_events_strs[] = {
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  25) 	[ilog2(DISK_EVENT_MEDIA_CHANGE)]	= "media_change",
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  26) 	[ilog2(DISK_EVENT_EJECT_REQUEST)]	= "eject_request",
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  27) };
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  28) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  29) static char *disk_uevents[] = {
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  30) 	[ilog2(DISK_EVENT_MEDIA_CHANGE)]	= "DISK_MEDIA_CHANGE=1",
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  31) 	[ilog2(DISK_EVENT_EJECT_REQUEST)]	= "DISK_EJECT_REQUEST=1",
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  32) };
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  33) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  34) /* list of all disk_events */
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  35) static DEFINE_MUTEX(disk_events_mutex);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  36) static LIST_HEAD(disk_events);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  37) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  38) /* disable in-kernel polling by default */
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  39) static unsigned long disk_events_dfl_poll_msecs;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  40) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  41) static unsigned long disk_events_poll_jiffies(struct gendisk *disk)
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  42) {
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  43) 	struct disk_events *ev = disk->ev;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  44) 	long intv_msecs = 0;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  45) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  46) 	/*
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  47) 	 * If device-specific poll interval is set, always use it.  If
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  48) 	 * the default is being used, poll if the POLL flag is set.
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  49) 	 */
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  50) 	if (ev->poll_msecs >= 0)
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  51) 		intv_msecs = ev->poll_msecs;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  52) 	else if (disk->event_flags & DISK_EVENT_FLAG_POLL)
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  53) 		intv_msecs = disk_events_dfl_poll_msecs;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  54) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  55) 	return msecs_to_jiffies(intv_msecs);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  56) }
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  57) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  58) /**
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  59)  * disk_block_events - block and flush disk event checking
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  60)  * @disk: disk to block events for
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  61)  *
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  62)  * On return from this function, it is guaranteed that event checking
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  63)  * isn't in progress and won't happen until unblocked by
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  64)  * disk_unblock_events().  Events blocking is counted and the actual
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  65)  * unblocking happens after the matching number of unblocks are done.
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  66)  *
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  67)  * Note that this intentionally does not block event checking from
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  68)  * disk_clear_events().
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  69)  *
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  70)  * CONTEXT:
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  71)  * Might sleep.
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  72)  */
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  73) void disk_block_events(struct gendisk *disk)
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  74) {
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  75) 	struct disk_events *ev = disk->ev;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  76) 	unsigned long flags;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  77) 	bool cancel;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  78) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  79) 	if (!ev)
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  80) 		return;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  81) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  82) 	/*
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  83) 	 * Outer mutex ensures that the first blocker completes canceling
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  84) 	 * the event work before further blockers are allowed to finish.
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  85) 	 */
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  86) 	mutex_lock(&ev->block_mutex);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  87) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  88) 	spin_lock_irqsave(&ev->lock, flags);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  89) 	cancel = !ev->block++;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  90) 	spin_unlock_irqrestore(&ev->lock, flags);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  91) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  92) 	if (cancel)
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  93) 		cancel_delayed_work_sync(&disk->ev->dwork);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  94) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  95) 	mutex_unlock(&ev->block_mutex);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  96) }
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  97) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  98) static void __disk_unblock_events(struct gendisk *disk, bool check_now)
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200  99) {
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 100) 	struct disk_events *ev = disk->ev;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 101) 	unsigned long intv;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 102) 	unsigned long flags;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 103) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 104) 	spin_lock_irqsave(&ev->lock, flags);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 105) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 106) 	if (WARN_ON_ONCE(ev->block <= 0))
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 107) 		goto out_unlock;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 108) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 109) 	if (--ev->block)
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 110) 		goto out_unlock;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 111) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 112) 	intv = disk_events_poll_jiffies(disk);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 113) 	if (check_now)
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 114) 		queue_delayed_work(system_freezable_power_efficient_wq,
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 115) 				&ev->dwork, 0);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 116) 	else if (intv)
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 117) 		queue_delayed_work(system_freezable_power_efficient_wq,
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 118) 				&ev->dwork, intv);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 119) out_unlock:
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 120) 	spin_unlock_irqrestore(&ev->lock, flags);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 121) }
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 122) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 123) /**
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 124)  * disk_unblock_events - unblock disk event checking
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 125)  * @disk: disk to unblock events for
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 126)  *
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 127)  * Undo disk_block_events().  When the block count reaches zero, it
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 128)  * starts events polling if configured.
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 129)  *
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 130)  * CONTEXT:
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 131)  * Don't care.  Safe to call from irq context.
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 132)  */
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 133) void disk_unblock_events(struct gendisk *disk)
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 134) {
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 135) 	if (disk->ev)
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 136) 		__disk_unblock_events(disk, false);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 137) }
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 138) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 139) /**
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 140)  * disk_flush_events - schedule immediate event checking and flushing
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 141)  * @disk: disk to check and flush events for
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 142)  * @mask: events to flush
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 143)  *
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 144)  * Schedule immediate event checking on @disk if not blocked.  Events in
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 145)  * @mask are scheduled to be cleared from the driver.  Note that this
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 146)  * doesn't clear the events from @disk->ev.
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 147)  *
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 148)  * CONTEXT:
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 149)  * If @mask is non-zero must be called with disk->open_mutex held.
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 150)  */
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 151) void disk_flush_events(struct gendisk *disk, unsigned int mask)
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 152) {
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 153) 	struct disk_events *ev = disk->ev;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 154) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 155) 	if (!ev)
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 156) 		return;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 157) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 158) 	spin_lock_irq(&ev->lock);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 159) 	ev->clearing |= mask;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 160) 	if (!ev->block)
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 161) 		mod_delayed_work(system_freezable_power_efficient_wq,
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 162) 				&ev->dwork, 0);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 163) 	spin_unlock_irq(&ev->lock);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 164) }
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 165) 
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 166) /*
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 167)  * Tell userland about new events.  Only the events listed in @disk->events are
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 168)  * reported, and only if DISK_EVENT_FLAG_UEVENT is set.  Otherwise, events are
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 169)  * processed internally but never get reported to userland.
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 170)  */
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 171) static void disk_event_uevent(struct gendisk *disk, unsigned int events)
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 172) {
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 173) 	char *envp[ARRAY_SIZE(disk_uevents) + 1] = { };
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 174) 	int nr_events = 0, i;
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 175) 
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 176) 	for (i = 0; i < ARRAY_SIZE(disk_uevents); i++)
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 177) 		if (events & disk->events & (1 << i))
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 178) 			envp[nr_events++] = disk_uevents[i];
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 179) 
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 180) 	if (nr_events)
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 181) 		kobject_uevent_env(&disk_to_dev(disk)->kobj, KOBJ_CHANGE, envp);
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 182) }
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 183) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 184) static void disk_check_events(struct disk_events *ev,
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 185) 			      unsigned int *clearing_ptr)
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 186) {
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 187) 	struct gendisk *disk = ev->disk;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 188) 	unsigned int clearing = *clearing_ptr;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 189) 	unsigned int events;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 190) 	unsigned long intv;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 191) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 192) 	/* check events */
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 193) 	events = disk->fops->check_events(disk, clearing);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 194) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 195) 	/* accumulate pending events and schedule next poll if necessary */
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 196) 	spin_lock_irq(&ev->lock);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 197) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 198) 	events &= ~ev->pending;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 199) 	ev->pending |= events;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 200) 	*clearing_ptr &= ~clearing;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 201) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 202) 	intv = disk_events_poll_jiffies(disk);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 203) 	if (!ev->block && intv)
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 204) 		queue_delayed_work(system_freezable_power_efficient_wq,
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 205) 				&ev->dwork, intv);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 206) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 207) 	spin_unlock_irq(&ev->lock);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 208) 
cf179948554a2 (Matteo Croce      2021-07-13 01:05:25 +0200 209) 	if (events & DISK_EVENT_MEDIA_CHANGE)
cf179948554a2 (Matteo Croce      2021-07-13 01:05:25 +0200 210) 		inc_diskseq(disk);
cf179948554a2 (Matteo Croce      2021-07-13 01:05:25 +0200 211) 
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 212) 	if (disk->event_flags & DISK_EVENT_FLAG_UEVENT)
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 213) 		disk_event_uevent(disk, events);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 214) }
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 215) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 216) /**
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 217)  * disk_clear_events - synchronously check, clear and return pending events
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 218)  * @disk: disk to fetch and clear events from
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 219)  * @mask: mask of events to be fetched and cleared
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 220)  *
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 221)  * Disk events are synchronously checked and pending events in @mask
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 222)  * are cleared and returned.  This ignores the block count.
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 223)  *
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 224)  * CONTEXT:
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 225)  * Might sleep.
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 226)  */
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 227) static unsigned int disk_clear_events(struct gendisk *disk, unsigned int mask)
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 228) {
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 229) 	struct disk_events *ev = disk->ev;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 230) 	unsigned int pending;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 231) 	unsigned int clearing = mask;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 232) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 233) 	if (!ev)
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 234) 		return 0;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 235) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 236) 	disk_block_events(disk);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 237) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 238) 	/*
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 239) 	 * store the union of mask and ev->clearing on the stack so that the
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 240) 	 * race with disk_flush_events does not cause ambiguity (ev->clearing
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 241) 	 * can still be modified even if events are blocked).
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 242) 	 */
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 243) 	spin_lock_irq(&ev->lock);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 244) 	clearing |= ev->clearing;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 245) 	ev->clearing = 0;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 246) 	spin_unlock_irq(&ev->lock);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 247) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 248) 	disk_check_events(ev, &clearing);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 249) 	/*
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 250) 	 * if ev->clearing is not 0, the disk_flush_events got called in the
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 251) 	 * middle of this function, so we want to run the workfn without delay.
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 252) 	 */
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 253) 	__disk_unblock_events(disk, ev->clearing ? true : false);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 254) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 255) 	/* then, fetch and clear pending events */
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 256) 	spin_lock_irq(&ev->lock);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 257) 	pending = ev->pending & mask;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 258) 	ev->pending &= ~mask;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 259) 	spin_unlock_irq(&ev->lock);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 260) 	WARN_ON_ONCE(clearing & mask);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 261) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 262) 	return pending;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 263) }
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 264) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 265) /**
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 266)  * bdev_check_media_change - check if a removable media has been changed
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 267)  * @bdev: block device to check
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 268)  *
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 269)  * Check whether a removable media has been changed, and attempt to free all
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 270)  * dentries and inodes and invalidates all block device page cache entries in
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 271)  * that case.
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 272)  *
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 273)  * Returns %true if the block device changed, or %false if not.
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 274)  */
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 275) bool bdev_check_media_change(struct block_device *bdev)
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 276) {
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 277) 	unsigned int events;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 278) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 279) 	events = disk_clear_events(bdev->bd_disk, DISK_EVENT_MEDIA_CHANGE |
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 280) 				   DISK_EVENT_EJECT_REQUEST);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 281) 	if (!(events & DISK_EVENT_MEDIA_CHANGE))
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 282) 		return false;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 283) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 284) 	if (__invalidate_device(bdev, true))
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 285) 		pr_warn("VFS: busy inodes on changed media %s\n",
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 286) 			bdev->bd_disk->disk_name);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 287) 	set_bit(GD_NEED_PART_SCAN, &bdev->bd_disk->state);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 288) 	return true;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 289) }
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 290) EXPORT_SYMBOL(bdev_check_media_change);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 291) 
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 292) /**
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 293)  * disk_force_media_change - force a media change event
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 294)  * @disk: the disk which will raise the event
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 295)  * @events: the events to raise
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 296)  *
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 297)  * Generate uevents for the disk. If DISK_EVENT_MEDIA_CHANGE is present,
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 298)  * attempt to free all dentries and inodes and invalidates all block
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 299)  * device page cache entries in that case.
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 300)  *
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 301)  * Returns %true if DISK_EVENT_MEDIA_CHANGE was raised, or %false if not.
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 302)  */
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 303) bool disk_force_media_change(struct gendisk *disk, unsigned int events)
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 304) {
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 305) 	disk_event_uevent(disk, events);
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 306) 
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 307) 	if (!(events & DISK_EVENT_MEDIA_CHANGE))
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 308) 		return false;
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 309) 
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 310) 	if (__invalidate_device(disk->part0, true))
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 311) 		pr_warn("VFS: busy inodes on changed media %s\n",
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 312) 			disk->disk_name);
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 313) 	set_bit(GD_NEED_PART_SCAN, &disk->state);
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 314) 	return true;
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 315) }
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 316) EXPORT_SYMBOL_GPL(disk_force_media_change);
e6138dc12de9d (Matteo Croce      2021-07-13 01:05:29 +0200 317) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 318) /*
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 319)  * Separate this part out so that a different pointer for clearing_ptr can be
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 320)  * passed in for disk_clear_events.
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 321)  */
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 322) static void disk_events_workfn(struct work_struct *work)
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 323) {
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 324) 	struct delayed_work *dwork = to_delayed_work(work);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 325) 	struct disk_events *ev = container_of(dwork, struct disk_events, dwork);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 326) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 327) 	disk_check_events(ev, &ev->clearing);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 328) }
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 329) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 330) /*
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 331)  * A disk events enabled device has the following sysfs nodes under
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 332)  * its /sys/block/X/ directory.
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 333)  *
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 334)  * events		: list of all supported events
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 335)  * events_async		: list of events which can be detected w/o polling
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 336)  *			  (always empty, only for backwards compatibility)
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 337)  * events_poll_msecs	: polling interval, 0: disable, -1: system default
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 338)  */
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 339) static ssize_t __disk_events_show(unsigned int events, char *buf)
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 340) {
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 341) 	const char *delim = "";
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 342) 	ssize_t pos = 0;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 343) 	int i;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 344) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 345) 	for (i = 0; i < ARRAY_SIZE(disk_events_strs); i++)
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 346) 		if (events & (1 << i)) {
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 347) 			pos += sprintf(buf + pos, "%s%s",
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 348) 				       delim, disk_events_strs[i]);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 349) 			delim = " ";
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 350) 		}
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 351) 	if (pos)
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 352) 		pos += sprintf(buf + pos, "\n");
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 353) 	return pos;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 354) }
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 355) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 356) static ssize_t disk_events_show(struct device *dev,
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 357) 				struct device_attribute *attr, char *buf)
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 358) {
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 359) 	struct gendisk *disk = dev_to_disk(dev);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 360) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 361) 	if (!(disk->event_flags & DISK_EVENT_FLAG_UEVENT))
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 362) 		return 0;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 363) 	return __disk_events_show(disk->events, buf);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 364) }
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 365) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 366) static ssize_t disk_events_async_show(struct device *dev,
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 367) 				      struct device_attribute *attr, char *buf)
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 368) {
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 369) 	return 0;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 370) }
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 371) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 372) static ssize_t disk_events_poll_msecs_show(struct device *dev,
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 373) 					   struct device_attribute *attr,
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 374) 					   char *buf)
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 375) {
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 376) 	struct gendisk *disk = dev_to_disk(dev);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 377) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 378) 	if (!disk->ev)
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 379) 		return sprintf(buf, "-1\n");
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 380) 	return sprintf(buf, "%ld\n", disk->ev->poll_msecs);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 381) }
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 382) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 383) static ssize_t disk_events_poll_msecs_store(struct device *dev,
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 384) 					    struct device_attribute *attr,
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 385) 					    const char *buf, size_t count)
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 386) {
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 387) 	struct gendisk *disk = dev_to_disk(dev);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 388) 	long intv;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 389) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 390) 	if (!count || !sscanf(buf, "%ld", &intv))
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 391) 		return -EINVAL;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 392) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 393) 	if (intv < 0 && intv != -1)
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 394) 		return -EINVAL;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 395) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 396) 	if (!disk->ev)
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 397) 		return -ENODEV;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 398) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 399) 	disk_block_events(disk);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 400) 	disk->ev->poll_msecs = intv;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 401) 	__disk_unblock_events(disk, true);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 402) 	return count;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 403) }
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 404) 
2bc8cda5ea4b4 (Christoph Hellwig 2021-06-24 09:38:43 +0200 405) DEVICE_ATTR(events, 0444, disk_events_show, NULL);
2bc8cda5ea4b4 (Christoph Hellwig 2021-06-24 09:38:43 +0200 406) DEVICE_ATTR(events_async, 0444, disk_events_async_show, NULL);
2bc8cda5ea4b4 (Christoph Hellwig 2021-06-24 09:38:43 +0200 407) DEVICE_ATTR(events_poll_msecs, 0644, disk_events_poll_msecs_show,
2bc8cda5ea4b4 (Christoph Hellwig 2021-06-24 09:38:43 +0200 408) 	    disk_events_poll_msecs_store);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 409) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 410) /*
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 411)  * The default polling interval can be specified by the kernel
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 412)  * parameter block.events_dfl_poll_msecs which defaults to 0
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 413)  * (disable).  This can also be modified runtime by writing to
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 414)  * /sys/module/block/parameters/events_dfl_poll_msecs.
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 415)  */
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 416) static int disk_events_set_dfl_poll_msecs(const char *val,
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 417) 					  const struct kernel_param *kp)
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 418) {
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 419) 	struct disk_events *ev;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 420) 	int ret;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 421) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 422) 	ret = param_set_ulong(val, kp);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 423) 	if (ret < 0)
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 424) 		return ret;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 425) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 426) 	mutex_lock(&disk_events_mutex);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 427) 	list_for_each_entry(ev, &disk_events, node)
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 428) 		disk_flush_events(ev->disk, 0);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 429) 	mutex_unlock(&disk_events_mutex);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 430) 	return 0;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 431) }
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 432) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 433) static const struct kernel_param_ops disk_events_dfl_poll_msecs_param_ops = {
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 434) 	.set	= disk_events_set_dfl_poll_msecs,
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 435) 	.get	= param_get_ulong,
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 436) };
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 437) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 438) #undef MODULE_PARAM_PREFIX
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 439) #define MODULE_PARAM_PREFIX	"block."
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 440) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 441) module_param_cb(events_dfl_poll_msecs, &disk_events_dfl_poll_msecs_param_ops,
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 442) 		&disk_events_dfl_poll_msecs, 0644);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 443) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 444) /*
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 445)  * disk_{alloc|add|del|release}_events - initialize and destroy disk_events.
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 446)  */
92e7755ebc692 (Luis Chamberlain  2021-08-18 16:45:39 +0200 447) int disk_alloc_events(struct gendisk *disk)
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 448) {
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 449) 	struct disk_events *ev;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 450) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 451) 	if (!disk->fops->check_events || !disk->events)
92e7755ebc692 (Luis Chamberlain  2021-08-18 16:45:39 +0200 452) 		return 0;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 453) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 454) 	ev = kzalloc(sizeof(*ev), GFP_KERNEL);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 455) 	if (!ev) {
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 456) 		pr_warn("%s: failed to initialize events\n", disk->disk_name);
92e7755ebc692 (Luis Chamberlain  2021-08-18 16:45:39 +0200 457) 		return -ENOMEM;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 458) 	}
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 459) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 460) 	INIT_LIST_HEAD(&ev->node);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 461) 	ev->disk = disk;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 462) 	spin_lock_init(&ev->lock);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 463) 	mutex_init(&ev->block_mutex);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 464) 	ev->block = 1;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 465) 	ev->poll_msecs = -1;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 466) 	INIT_DELAYED_WORK(&ev->dwork, disk_events_workfn);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 467) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 468) 	disk->ev = ev;
92e7755ebc692 (Luis Chamberlain  2021-08-18 16:45:39 +0200 469) 	return 0;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 470) }
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 471) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 472) void disk_add_events(struct gendisk *disk)
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 473) {
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 474) 	if (!disk->ev)
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 475) 		return;
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 476) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 477) 	mutex_lock(&disk_events_mutex);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 478) 	list_add_tail(&disk->ev->node, &disk_events);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 479) 	mutex_unlock(&disk_events_mutex);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 480) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 481) 	/*
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 482) 	 * Block count is initialized to 1 and the following initial
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 483) 	 * unblock kicks it into action.
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 484) 	 */
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 485) 	__disk_unblock_events(disk, true);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 486) }
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 487) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 488) void disk_del_events(struct gendisk *disk)
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 489) {
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 490) 	if (disk->ev) {
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 491) 		disk_block_events(disk);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 492) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 493) 		mutex_lock(&disk_events_mutex);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 494) 		list_del_init(&disk->ev->node);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 495) 		mutex_unlock(&disk_events_mutex);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 496) 	}
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 497) }
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 498) 
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 499) void disk_release_events(struct gendisk *disk)
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 500) {
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 501) 	/* the block count should be 1 from disk_del_events() */
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 502) 	WARN_ON_ONCE(disk->ev && disk->ev->block != 1);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 503) 	kfree(disk->ev);
d5870edfa3afc (Christoph Hellwig 2021-06-24 09:38:42 +0200 504) }