aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Wilck <mwilck@suse.com>2019-03-27 09:51:02 -0400
committerJens Axboe <axboe@kernel.dk>2019-04-12 15:35:24 -0400
commitc92e2f04b35938da23eb9a7f7101cbdd5ac7cdc4 (patch)
treef9ec276b627115f704333935e96787c35e1eb4a1
parent673387a930059fc4ad8060847a1d46f94e702281 (diff)
block: disk_events: introduce event flags
Currently, an empty disk->events field tells the block layer not to forward media change events to user space. This was done in commit 7c88a168da80 ("block: don't propagate unlisted DISK_EVENTs to userland") in order to avoid events from "fringe" drivers to be forwarded to user space. By doing so, the block layer lost the information which events were supported by a particular block device, and most importantly, whether or not a given device supports media change events at all. Prepare for not interpreting the "events" field this way in the future any more. This is done by adding an additional field "event_flags" to struct gendisk, and two flag bits that can be set to have the device treated like one that had the "events" field set to a non-zero value before. This applies only to the sd and sr drivers, which are changed to set the new flags. The new flags are DISK_EVENT_FLAG_POLL to enforce polling of the device for synchronous events, and DISK_EVENT_FLAG_UEVENT to tell the blocklayer to generate udev events from kernel events. In order to add the event_flags field to struct gendisk, the events field is converted to an "unsigned short"; it doesn't need to hold values bigger than 2 anyway. This patch doesn't change behavior. Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Martin Wilck <mwilck@suse.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r--block/genhd.c13
-rw-r--r--drivers/scsi/sd.c1
-rw-r--r--drivers/scsi/sr.c1
-rw-r--r--include/linux/genhd.h10
4 files changed, 20 insertions, 5 deletions
diff --git a/block/genhd.c b/block/genhd.c
index ee76de0fb4cc..5375be39e8a5 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -1632,7 +1632,7 @@ static unsigned long disk_events_poll_jiffies(struct gendisk *disk)
1632 */ 1632 */
1633 if (ev->poll_msecs >= 0) 1633 if (ev->poll_msecs >= 0)
1634 intv_msecs = ev->poll_msecs; 1634 intv_msecs = ev->poll_msecs;
1635 else if (disk->events) 1635 else if (disk->event_flags & DISK_EVENT_FLAG_POLL)
1636 intv_msecs = disk_events_dfl_poll_msecs; 1636 intv_msecs = disk_events_dfl_poll_msecs;
1637 1637
1638 return msecs_to_jiffies(intv_msecs); 1638 return msecs_to_jiffies(intv_msecs);
@@ -1842,11 +1842,13 @@ static void disk_check_events(struct disk_events *ev,
1842 1842
1843 /* 1843 /*
1844 * Tell userland about new events. Only the events listed in 1844 * Tell userland about new events. Only the events listed in
1845 * @disk->events are reported. Unlisted events are processed the 1845 * @disk->events are reported, and only if DISK_EVENT_FLAG_UEVENT
1846 * same internally but never get reported to userland. 1846 * is set. Otherwise, events are processed internally but never
1847 * get reported to userland.
1847 */ 1848 */
1848 for (i = 0; i < ARRAY_SIZE(disk_uevents); i++) 1849 for (i = 0; i < ARRAY_SIZE(disk_uevents); i++)
1849 if (events & disk->events & (1 << i)) 1850 if ((events & disk->events & (1 << i)) &&
1851 (disk->event_flags & DISK_EVENT_FLAG_UEVENT))
1850 envp[nr_events++] = disk_uevents[i]; 1852 envp[nr_events++] = disk_uevents[i];
1851 1853
1852 if (nr_events) 1854 if (nr_events)
@@ -1884,6 +1886,9 @@ static ssize_t disk_events_show(struct device *dev,
1884{ 1886{
1885 struct gendisk *disk = dev_to_disk(dev); 1887 struct gendisk *disk = dev_to_disk(dev);
1886 1888
1889 if (!(disk->event_flags & DISK_EVENT_FLAG_UEVENT))
1890 return 0;
1891
1887 return __disk_events_show(disk->events, buf); 1892 return __disk_events_show(disk->events, buf);
1888} 1893}
1889 1894
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 92c34d93e051..ebc80354714c 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -3293,6 +3293,7 @@ static void sd_probe_async(void *data, async_cookie_t cookie)
3293 if (sdp->removable) { 3293 if (sdp->removable) {
3294 gd->flags |= GENHD_FL_REMOVABLE; 3294 gd->flags |= GENHD_FL_REMOVABLE;
3295 gd->events |= DISK_EVENT_MEDIA_CHANGE; 3295 gd->events |= DISK_EVENT_MEDIA_CHANGE;
3296 gd->event_flags = DISK_EVENT_FLAG_POLL | DISK_EVENT_FLAG_UEVENT;
3296 } 3297 }
3297 3298
3298 blk_pm_runtime_init(sdp->request_queue, dev); 3299 blk_pm_runtime_init(sdp->request_queue, dev);
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 039c27c2d7b3..c3f443d5aea8 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -716,6 +716,7 @@ static int sr_probe(struct device *dev)
716 disk->fops = &sr_bdops; 716 disk->fops = &sr_bdops;
717 disk->flags = GENHD_FL_CD | GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE; 717 disk->flags = GENHD_FL_CD | GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE;
718 disk->events = DISK_EVENT_MEDIA_CHANGE | DISK_EVENT_EJECT_REQUEST; 718 disk->events = DISK_EVENT_MEDIA_CHANGE | DISK_EVENT_EJECT_REQUEST;
719 disk->event_flags = DISK_EVENT_FLAG_POLL | DISK_EVENT_FLAG_UEVENT;
719 720
720 blk_queue_rq_timeout(sdev->request_queue, SR_TIMEOUT); 721 blk_queue_rq_timeout(sdev->request_queue, SR_TIMEOUT);
721 722
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index a65d9fc17369..6547c9256d5c 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -150,6 +150,13 @@ enum {
150 DISK_EVENT_EJECT_REQUEST = 1 << 1, /* eject requested */ 150 DISK_EVENT_EJECT_REQUEST = 1 << 1, /* eject requested */
151}; 151};
152 152
153enum {
154 /* Poll even if events_poll_msecs is unset */
155 DISK_EVENT_FLAG_POLL = 1 << 0,
156 /* Forward events to udev */
157 DISK_EVENT_FLAG_UEVENT = 1 << 1,
158};
159
153struct disk_part_tbl { 160struct disk_part_tbl {
154 struct rcu_head rcu_head; 161 struct rcu_head rcu_head;
155 int len; 162 int len;
@@ -184,7 +191,8 @@ struct gendisk {
184 char disk_name[DISK_NAME_LEN]; /* name of major driver */ 191 char disk_name[DISK_NAME_LEN]; /* name of major driver */
185 char *(*devnode)(struct gendisk *gd, umode_t *mode); 192 char *(*devnode)(struct gendisk *gd, umode_t *mode);
186 193
187 unsigned int events; /* supported events */ 194 unsigned short events; /* supported events */
195 unsigned short event_flags; /* flags related to event processing */
188 196
189 /* Array of pointers to partitions indexed by partno. 197 /* Array of pointers to partitions indexed by partno.
190 * Protected with matching bdev lock but stat and other 198 * Protected with matching bdev lock but stat and other