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) }