All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Howells <dhowells@redhat.com>
To: viro@zeniv.linux.org.uk
Cc: dhowells@redhat.com, Casey Schaufler <casey@schaufler-ca.com>,
	Stephen Smalley <sds@tycho.nsa.gov>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	nicolas.dichtel@6wind.com, raven@themaw.net,
	Christian Brauner <christian@brauner.io>,
	dhowells@redhat.com, keyrings@vger.kernel.org,
	linux-usb@vger.kernel.org, linux-security-module@vger.kernel.org,
	linux-fsdevel@vger.kernel.org, linux-api@vger.kernel.org,
	linux-block@vger.kernel.org,
	linux-security-module@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: [PATCH 07/11] block: Add block layer notifications [ver #7]
Date: Fri, 30 Aug 2019 14:58:14 +0100	[thread overview]
Message-ID: <156717349477.2204.2264554813509459287.stgit@warthog.procyon.org.uk> (raw)
In-Reply-To: <156717343223.2204.15875738850129174524.stgit@warthog.procyon.org.uk>

Add a block layer notification mechanism whereby notifications about
block-layer events such as I/O errors, can be reported to a monitoring
process asynchronously.

Firstly, an event queue needs to be created:

	fd = open("/dev/event_queue", O_RDWR);
	ioctl(fd, IOC_WATCH_QUEUE_SET_SIZE, page_size << n);

then a notification can be set up to report block notifications via that
queue:

	struct watch_notification_filter filter = {
		.nr_filters = 1,
		.filters = {
			[0] = {
				.type = WATCH_TYPE_BLOCK_NOTIFY,
				.subtype_filter[0] = UINT_MAX;
			},
		},
	};
	ioctl(fd, IOC_WATCH_QUEUE_SET_FILTER, &filter);
	watch_devices(fd, 12);

After that, records will be placed into the queue when, for example, errors
occur on a block device.  Records are of the following format:

	struct block_notification {
		struct watch_notification watch;
		__u64	dev;
		__u64	sector;
	} *n;

Where:

	n->watch.type will be WATCH_TYPE_BLOCK_NOTIFY

	n->watch.subtype will be the type of notification, such as
	NOTIFY_BLOCK_ERROR_CRITICAL_MEDIUM.

	n->watch.info & WATCH_INFO_LENGTH will indicate the length of the
	record.

	n->watch.info & WATCH_INFO_ID will be the second argument to
	watch_devices(), shifted.

	n->dev will be the device numbers munged together.

	n->sector will indicate the affected sector (if appropriate for the
	event).

Note that it is permissible for event records to be of variable length -
or, at least, the length may be dependent on the subtype.

Signed-off-by: David Howells <dhowells@redhat.com>
---

 Documentation/watch_queue.rst    |    4 +++-
 block/Kconfig                    |    9 +++++++++
 block/blk-core.c                 |   29 +++++++++++++++++++++++++++++
 include/linux/blkdev.h           |   15 +++++++++++++++
 include/uapi/linux/watch_queue.h |   30 +++++++++++++++++++++++++++++-
 5 files changed, 85 insertions(+), 2 deletions(-)

diff --git a/Documentation/watch_queue.rst b/Documentation/watch_queue.rst
index 393905b904c8..5cc9c6924727 100644
--- a/Documentation/watch_queue.rst
+++ b/Documentation/watch_queue.rst
@@ -7,7 +7,9 @@ receive notifications from the kernel.  This can be used in conjunction with::
 
   * Key/keyring notifications
 
-  * General device event notifications
+  * General device event notifications, including::
+
+    * Block layer event notifications
 
 
 The notifications buffers can be enabled by:
diff --git a/block/Kconfig b/block/Kconfig
index 8b5f8e560eb4..cc93e4ca29a7 100644
--- a/block/Kconfig
+++ b/block/Kconfig
@@ -164,6 +164,15 @@ config BLK_SED_OPAL
 	Enabling this option enables users to setup/unlock/lock
 	Locking ranges for SED devices using the Opal protocol.
 
+config BLK_NOTIFICATIONS
+	bool "Block layer event notifications"
+	depends on DEVICE_NOTIFICATIONS
+	help
+	  This option provides support for getting block layer event
+	  notifications.  This makes use of the /dev/watch_queue misc device to
+	  handle the notification buffer and provides the device_notify() system
+	  call to enable/disable watches.
+
 menu "Partition Types"
 
 source "block/partitions/Kconfig"
diff --git a/block/blk-core.c b/block/blk-core.c
index d0cc6e14d2f0..8ab1e07aa311 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -181,6 +181,22 @@ static const struct {
 	[BLK_STS_IOERR]		= { -EIO,	"I/O" },
 };
 
+#ifdef CONFIG_BLK_NOTIFICATIONS
+static const
+enum block_notification_type blk_notifications[ARRAY_SIZE(blk_errors)] = {
+	[BLK_STS_TIMEOUT]	= NOTIFY_BLOCK_ERROR_TIMEOUT,
+	[BLK_STS_NOSPC]		= NOTIFY_BLOCK_ERROR_NO_SPACE,
+	[BLK_STS_TRANSPORT]	= NOTIFY_BLOCK_ERROR_RECOVERABLE_TRANSPORT,
+	[BLK_STS_TARGET]	= NOTIFY_BLOCK_ERROR_CRITICAL_TARGET,
+	[BLK_STS_NEXUS]		= NOTIFY_BLOCK_ERROR_CRITICAL_NEXUS,
+	[BLK_STS_MEDIUM]	= NOTIFY_BLOCK_ERROR_CRITICAL_MEDIUM,
+	[BLK_STS_PROTECTION]	= NOTIFY_BLOCK_ERROR_PROTECTION,
+	[BLK_STS_RESOURCE]	= NOTIFY_BLOCK_ERROR_KERNEL_RESOURCE,
+	[BLK_STS_DEV_RESOURCE]	= NOTIFY_BLOCK_ERROR_DEVICE_RESOURCE,
+	[BLK_STS_IOERR]		= NOTIFY_BLOCK_ERROR_IO,
+};
+#endif
+
 blk_status_t errno_to_blk_status(int errno)
 {
 	int i;
@@ -221,6 +237,19 @@ static void print_req_error(struct request *req, blk_status_t status,
 		req->cmd_flags & ~REQ_OP_MASK,
 		req->nr_phys_segments,
 		IOPRIO_PRIO_CLASS(req->ioprio));
+
+#ifdef CONFIG_BLK_NOTIFICATIONS
+	if (blk_notifications[idx]) {
+		struct block_notification n = {
+			.watch.type	= WATCH_TYPE_BLOCK_NOTIFY,
+			.watch.subtype	= blk_notifications[idx],
+			.watch.info	= watch_sizeof(n),
+			.dev		= req->rq_disk ? disk_devt(req->rq_disk) : 0,
+			.sector		= blk_rq_pos(req),
+		};
+		post_block_notification(&n);
+	}
+#endif
 }
 
 static void req_bio_endio(struct request *rq, struct bio *bio,
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 1ef375dafb1c..5d856f670a8f 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -27,6 +27,7 @@
 #include <linux/percpu-refcount.h>
 #include <linux/scatterlist.h>
 #include <linux/blkzoned.h>
+#include <linux/watch_queue.h>
 
 struct module;
 struct scsi_ioctl_command;
@@ -1742,6 +1743,20 @@ static inline bool blk_req_can_dispatch_to_zone(struct request *rq)
 }
 #endif /* CONFIG_BLK_DEV_ZONED */
 
+#ifdef CONFIG_BLK_NOTIFICATIONS
+static inline void post_block_notification(struct block_notification *n)
+{
+	u64 id = 0; /* Might want to allow dev# here. */
+
+	post_device_notification(&n->watch, id);
+}
+#else
+static inline void post_block_notification(struct block_notification *n)
+{
+}
+#endif
+
+
 #else /* CONFIG_BLOCK */
 
 struct block_device;
diff --git a/include/uapi/linux/watch_queue.h b/include/uapi/linux/watch_queue.h
index 654d4ba8b909..9a6c059af09d 100644
--- a/include/uapi/linux/watch_queue.h
+++ b/include/uapi/linux/watch_queue.h
@@ -11,7 +11,8 @@
 enum watch_notification_type {
 	WATCH_TYPE_META		= 0,	/* Special record */
 	WATCH_TYPE_KEY_NOTIFY	= 1,	/* Key change event notification */
-	WATCH_TYPE___NR		= 2
+	WATCH_TYPE_BLOCK_NOTIFY	= 2,	/* Block layer event notification */
+	WATCH_TYPE___NR		= 3
 };
 
 enum watch_meta_notification_subtype {
@@ -124,4 +125,31 @@ struct key_notification {
 	__u32	aux;		/* Per-type auxiliary data */
 };
 
+/*
+ * Type of block layer notification.
+ */
+enum block_notification_type {
+	NOTIFY_BLOCK_ERROR_TIMEOUT		= 1, /* Timeout error */
+	NOTIFY_BLOCK_ERROR_NO_SPACE		= 2, /* Critical space allocation error */
+	NOTIFY_BLOCK_ERROR_RECOVERABLE_TRANSPORT = 3, /* Recoverable transport error */
+	NOTIFY_BLOCK_ERROR_CRITICAL_TARGET	= 4, /* Critical target error */
+	NOTIFY_BLOCK_ERROR_CRITICAL_NEXUS	= 5, /* Critical nexus error */
+	NOTIFY_BLOCK_ERROR_CRITICAL_MEDIUM	= 6, /* Critical medium error */
+	NOTIFY_BLOCK_ERROR_PROTECTION		= 7, /* Protection error */
+	NOTIFY_BLOCK_ERROR_KERNEL_RESOURCE	= 8, /* Kernel resource error */
+	NOTIFY_BLOCK_ERROR_DEVICE_RESOURCE	= 9, /* Device resource error */
+	NOTIFY_BLOCK_ERROR_IO			= 10, /* Other I/O error */
+};
+
+/*
+ * Block layer notification record.
+ * - watch.type = WATCH_TYPE_BLOCK_NOTIFY
+ * - watch.subtype = enum block_notification_type
+ */
+struct block_notification {
+	struct watch_notification watch; /* WATCH_TYPE_BLOCK_NOTIFY */
+	__u64	dev;			/* Device number */
+	__u64	sector;			/* Affected sector */
+};
+
 #endif /* _UAPI_LINUX_WATCH_QUEUE_H */


WARNING: multiple messages have this Message-ID (diff)
From: David Howells <dhowells@redhat.com>
To: viro@zeniv.linux.org.uk
Cc: dhowells@redhat.com, Casey Schaufler <casey@schaufler-ca.com>,
	Stephen Smalley <sds@tycho.nsa.gov>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	nicolas.dichtel@6wind.com, raven@themaw.net,
	Christian Brauner <christian@brauner.io>dhowells@redhat.com,
	keyrings@vger.kernel.org, linux-usb@vger.kernel.org,
	linux-security-module@vger.kernel.org,
	linux-fsdevel@vger.kernel.org,
	linux-api@vger.kernel.org@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: [PATCH 07/11] block: Add block layer notifications [ver #7]
Date: Fri, 30 Aug 2019 13:58:14 +0000	[thread overview]
Message-ID: <156717349477.2204.2264554813509459287.stgit@warthog.procyon.org.uk> (raw)
In-Reply-To: <156717343223.2204.15875738850129174524.stgit@warthog.procyon.org.uk>

Add a block layer notification mechanism whereby notifications about
block-layer events such as I/O errors, can be reported to a monitoring
process asynchronously.

Firstly, an event queue needs to be created:

	fd = open("/dev/event_queue", O_RDWR);
	ioctl(fd, IOC_WATCH_QUEUE_SET_SIZE, page_size << n);

then a notification can be set up to report block notifications via that
queue:

	struct watch_notification_filter filter = {
		.nr_filters = 1,
		.filters = {
			[0] = {
				.type = WATCH_TYPE_BLOCK_NOTIFY,
				.subtype_filter[0] = UINT_MAX;
			},
		},
	};
	ioctl(fd, IOC_WATCH_QUEUE_SET_FILTER, &filter);
	watch_devices(fd, 12);

After that, records will be placed into the queue when, for example, errors
occur on a block device.  Records are of the following format:

	struct block_notification {
		struct watch_notification watch;
		__u64	dev;
		__u64	sector;
	} *n;

Where:

	n->watch.type will be WATCH_TYPE_BLOCK_NOTIFY

	n->watch.subtype will be the type of notification, such as
	NOTIFY_BLOCK_ERROR_CRITICAL_MEDIUM.

	n->watch.info & WATCH_INFO_LENGTH will indicate the length of the
	record.

	n->watch.info & WATCH_INFO_ID will be the second argument to
	watch_devices(), shifted.

	n->dev will be the device numbers munged together.

	n->sector will indicate the affected sector (if appropriate for the
	event).

Note that it is permissible for event records to be of variable length -
or, at least, the length may be dependent on the subtype.

Signed-off-by: David Howells <dhowells@redhat.com>
---

 Documentation/watch_queue.rst    |    4 +++-
 block/Kconfig                    |    9 +++++++++
 block/blk-core.c                 |   29 +++++++++++++++++++++++++++++
 include/linux/blkdev.h           |   15 +++++++++++++++
 include/uapi/linux/watch_queue.h |   30 +++++++++++++++++++++++++++++-
 5 files changed, 85 insertions(+), 2 deletions(-)

diff --git a/Documentation/watch_queue.rst b/Documentation/watch_queue.rst
index 393905b904c8..5cc9c6924727 100644
--- a/Documentation/watch_queue.rst
+++ b/Documentation/watch_queue.rst
@@ -7,7 +7,9 @@ receive notifications from the kernel.  This can be used in conjunction with::
 
   * Key/keyring notifications
 
-  * General device event notifications
+  * General device event notifications, including::
+
+    * Block layer event notifications
 
 
 The notifications buffers can be enabled by:
diff --git a/block/Kconfig b/block/Kconfig
index 8b5f8e560eb4..cc93e4ca29a7 100644
--- a/block/Kconfig
+++ b/block/Kconfig
@@ -164,6 +164,15 @@ config BLK_SED_OPAL
 	Enabling this option enables users to setup/unlock/lock
 	Locking ranges for SED devices using the Opal protocol.
 
+config BLK_NOTIFICATIONS
+	bool "Block layer event notifications"
+	depends on DEVICE_NOTIFICATIONS
+	help
+	  This option provides support for getting block layer event
+	  notifications.  This makes use of the /dev/watch_queue misc device to
+	  handle the notification buffer and provides the device_notify() system
+	  call to enable/disable watches.
+
 menu "Partition Types"
 
 source "block/partitions/Kconfig"
diff --git a/block/blk-core.c b/block/blk-core.c
index d0cc6e14d2f0..8ab1e07aa311 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -181,6 +181,22 @@ static const struct {
 	[BLK_STS_IOERR]		= { -EIO,	"I/O" },
 };
 
+#ifdef CONFIG_BLK_NOTIFICATIONS
+static const
+enum block_notification_type blk_notifications[ARRAY_SIZE(blk_errors)] = {
+	[BLK_STS_TIMEOUT]	= NOTIFY_BLOCK_ERROR_TIMEOUT,
+	[BLK_STS_NOSPC]		= NOTIFY_BLOCK_ERROR_NO_SPACE,
+	[BLK_STS_TRANSPORT]	= NOTIFY_BLOCK_ERROR_RECOVERABLE_TRANSPORT,
+	[BLK_STS_TARGET]	= NOTIFY_BLOCK_ERROR_CRITICAL_TARGET,
+	[BLK_STS_NEXUS]		= NOTIFY_BLOCK_ERROR_CRITICAL_NEXUS,
+	[BLK_STS_MEDIUM]	= NOTIFY_BLOCK_ERROR_CRITICAL_MEDIUM,
+	[BLK_STS_PROTECTION]	= NOTIFY_BLOCK_ERROR_PROTECTION,
+	[BLK_STS_RESOURCE]	= NOTIFY_BLOCK_ERROR_KERNEL_RESOURCE,
+	[BLK_STS_DEV_RESOURCE]	= NOTIFY_BLOCK_ERROR_DEVICE_RESOURCE,
+	[BLK_STS_IOERR]		= NOTIFY_BLOCK_ERROR_IO,
+};
+#endif
+
 blk_status_t errno_to_blk_status(int errno)
 {
 	int i;
@@ -221,6 +237,19 @@ static void print_req_error(struct request *req, blk_status_t status,
 		req->cmd_flags & ~REQ_OP_MASK,
 		req->nr_phys_segments,
 		IOPRIO_PRIO_CLASS(req->ioprio));
+
+#ifdef CONFIG_BLK_NOTIFICATIONS
+	if (blk_notifications[idx]) {
+		struct block_notification n = {
+			.watch.type	= WATCH_TYPE_BLOCK_NOTIFY,
+			.watch.subtype	= blk_notifications[idx],
+			.watch.info	= watch_sizeof(n),
+			.dev		= req->rq_disk ? disk_devt(req->rq_disk) : 0,
+			.sector		= blk_rq_pos(req),
+		};
+		post_block_notification(&n);
+	}
+#endif
 }
 
 static void req_bio_endio(struct request *rq, struct bio *bio,
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 1ef375dafb1c..5d856f670a8f 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -27,6 +27,7 @@
 #include <linux/percpu-refcount.h>
 #include <linux/scatterlist.h>
 #include <linux/blkzoned.h>
+#include <linux/watch_queue.h>
 
 struct module;
 struct scsi_ioctl_command;
@@ -1742,6 +1743,20 @@ static inline bool blk_req_can_dispatch_to_zone(struct request *rq)
 }
 #endif /* CONFIG_BLK_DEV_ZONED */
 
+#ifdef CONFIG_BLK_NOTIFICATIONS
+static inline void post_block_notification(struct block_notification *n)
+{
+	u64 id = 0; /* Might want to allow dev# here. */
+
+	post_device_notification(&n->watch, id);
+}
+#else
+static inline void post_block_notification(struct block_notification *n)
+{
+}
+#endif
+
+
 #else /* CONFIG_BLOCK */
 
 struct block_device;
diff --git a/include/uapi/linux/watch_queue.h b/include/uapi/linux/watch_queue.h
index 654d4ba8b909..9a6c059af09d 100644
--- a/include/uapi/linux/watch_queue.h
+++ b/include/uapi/linux/watch_queue.h
@@ -11,7 +11,8 @@
 enum watch_notification_type {
 	WATCH_TYPE_META		= 0,	/* Special record */
 	WATCH_TYPE_KEY_NOTIFY	= 1,	/* Key change event notification */
-	WATCH_TYPE___NR		= 2
+	WATCH_TYPE_BLOCK_NOTIFY	= 2,	/* Block layer event notification */
+	WATCH_TYPE___NR		= 3
 };
 
 enum watch_meta_notification_subtype {
@@ -124,4 +125,31 @@ struct key_notification {
 	__u32	aux;		/* Per-type auxiliary data */
 };
 
+/*
+ * Type of block layer notification.
+ */
+enum block_notification_type {
+	NOTIFY_BLOCK_ERROR_TIMEOUT		= 1, /* Timeout error */
+	NOTIFY_BLOCK_ERROR_NO_SPACE		= 2, /* Critical space allocation error */
+	NOTIFY_BLOCK_ERROR_RECOVERABLE_TRANSPORT = 3, /* Recoverable transport error */
+	NOTIFY_BLOCK_ERROR_CRITICAL_TARGET	= 4, /* Critical target error */
+	NOTIFY_BLOCK_ERROR_CRITICAL_NEXUS	= 5, /* Critical nexus error */
+	NOTIFY_BLOCK_ERROR_CRITICAL_MEDIUM	= 6, /* Critical medium error */
+	NOTIFY_BLOCK_ERROR_PROTECTION		= 7, /* Protection error */
+	NOTIFY_BLOCK_ERROR_KERNEL_RESOURCE	= 8, /* Kernel resource error */
+	NOTIFY_BLOCK_ERROR_DEVICE_RESOURCE	= 9, /* Device resource error */
+	NOTIFY_BLOCK_ERROR_IO			= 10, /* Other I/O error */
+};
+
+/*
+ * Block layer notification record.
+ * - watch.type = WATCH_TYPE_BLOCK_NOTIFY
+ * - watch.subtype = enum block_notification_type
+ */
+struct block_notification {
+	struct watch_notification watch; /* WATCH_TYPE_BLOCK_NOTIFY */
+	__u64	dev;			/* Device number */
+	__u64	sector;			/* Affected sector */
+};
+
 #endif /* _UAPI_LINUX_WATCH_QUEUE_H */

WARNING: multiple messages have this Message-ID (diff)
From: David Howells <dhowells@redhat.com>
To: viro@zeniv.linux.org.uk
Cc: dhowells@redhat.com, Casey Schaufler <casey@schaufler-ca.com>,
	Stephen Smalley <sds@tycho.nsa.gov>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	nicolas.dichtel@6wind.com, raven@themaw.net,
	Christian Brauner <christian@brauner.io>dhowells@redhat.com,
	keyrings@vger.kernel.org, linux-usb@vger.kernel.org,
	linux-security-module@vger.kernel.org,
	linux-fsdevel@vger.kernel.org, linux-api@vger.kernel.org,
	linux-block@vger.kernel.orglinux-security-module@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: [PATCH 07/11] block: Add block layer notifications [ver #7]
Date: Fri, 30 Aug 2019 14:58:14 +0100	[thread overview]
Message-ID: <156717349477.2204.2264554813509459287.stgit@warthog.procyon.org.uk> (raw)
In-Reply-To: <156717343223.2204.15875738850129174524.stgit@warthog.procyon.org.uk>

Add a block layer notification mechanism whereby notifications about
block-layer events such as I/O errors, can be reported to a monitoring
process asynchronously.

Firstly, an event queue needs to be created:

	fd = open("/dev/event_queue", O_RDWR);
	ioctl(fd, IOC_WATCH_QUEUE_SET_SIZE, page_size << n);

then a notification can be set up to report block notifications via that
queue:

	struct watch_notification_filter filter = {
		.nr_filters = 1,
		.filters = {
			[0] = {
				.type = WATCH_TYPE_BLOCK_NOTIFY,
				.subtype_filter[0] = UINT_MAX;
			},
		},
	};
	ioctl(fd, IOC_WATCH_QUEUE_SET_FILTER, &filter);
	watch_devices(fd, 12);

After that, records will be placed into the queue when, for example, errors
occur on a block device.  Records are of the following format:

	struct block_notification {
		struct watch_notification watch;
		__u64	dev;
		__u64	sector;
	} *n;

Where:

	n->watch.type will be WATCH_TYPE_BLOCK_NOTIFY

	n->watch.subtype will be the type of notification, such as
	NOTIFY_BLOCK_ERROR_CRITICAL_MEDIUM.

	n->watch.info & WATCH_INFO_LENGTH will indicate the length of the
	record.

	n->watch.info & WATCH_INFO_ID will be the second argument to
	watch_devices(), shifted.

	n->dev will be the device numbers munged together.

	n->sector will indicate the affected sector (if appropriate for the
	event).

Note that it is permissible for event records to be of variable length -
or, at least, the length may be dependent on the subtype.

Signed-off-by: David Howells <dhowells@redhat.com>
---

 Documentation/watch_queue.rst    |    4 +++-
 block/Kconfig                    |    9 +++++++++
 block/blk-core.c                 |   29 +++++++++++++++++++++++++++++
 include/linux/blkdev.h           |   15 +++++++++++++++
 include/uapi/linux/watch_queue.h |   30 +++++++++++++++++++++++++++++-
 5 files changed, 85 insertions(+), 2 deletions(-)

diff --git a/Documentation/watch_queue.rst b/Documentation/watch_queue.rst
index 393905b904c8..5cc9c6924727 100644
--- a/Documentation/watch_queue.rst
+++ b/Documentation/watch_queue.rst
@@ -7,7 +7,9 @@ receive notifications from the kernel.  This can be used in conjunction with::
 
   * Key/keyring notifications
 
-  * General device event notifications
+  * General device event notifications, including::
+
+    * Block layer event notifications
 
 
 The notifications buffers can be enabled by:
diff --git a/block/Kconfig b/block/Kconfig
index 8b5f8e560eb4..cc93e4ca29a7 100644
--- a/block/Kconfig
+++ b/block/Kconfig
@@ -164,6 +164,15 @@ config BLK_SED_OPAL
 	Enabling this option enables users to setup/unlock/lock
 	Locking ranges for SED devices using the Opal protocol.
 
+config BLK_NOTIFICATIONS
+	bool "Block layer event notifications"
+	depends on DEVICE_NOTIFICATIONS
+	help
+	  This option provides support for getting block layer event
+	  notifications.  This makes use of the /dev/watch_queue misc device to
+	  handle the notification buffer and provides the device_notify() system
+	  call to enable/disable watches.
+
 menu "Partition Types"
 
 source "block/partitions/Kconfig"
diff --git a/block/blk-core.c b/block/blk-core.c
index d0cc6e14d2f0..8ab1e07aa311 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -181,6 +181,22 @@ static const struct {
 	[BLK_STS_IOERR]		= { -EIO,	"I/O" },
 };
 
+#ifdef CONFIG_BLK_NOTIFICATIONS
+static const
+enum block_notification_type blk_notifications[ARRAY_SIZE(blk_errors)] = {
+	[BLK_STS_TIMEOUT]	= NOTIFY_BLOCK_ERROR_TIMEOUT,
+	[BLK_STS_NOSPC]		= NOTIFY_BLOCK_ERROR_NO_SPACE,
+	[BLK_STS_TRANSPORT]	= NOTIFY_BLOCK_ERROR_RECOVERABLE_TRANSPORT,
+	[BLK_STS_TARGET]	= NOTIFY_BLOCK_ERROR_CRITICAL_TARGET,
+	[BLK_STS_NEXUS]		= NOTIFY_BLOCK_ERROR_CRITICAL_NEXUS,
+	[BLK_STS_MEDIUM]	= NOTIFY_BLOCK_ERROR_CRITICAL_MEDIUM,
+	[BLK_STS_PROTECTION]	= NOTIFY_BLOCK_ERROR_PROTECTION,
+	[BLK_STS_RESOURCE]	= NOTIFY_BLOCK_ERROR_KERNEL_RESOURCE,
+	[BLK_STS_DEV_RESOURCE]	= NOTIFY_BLOCK_ERROR_DEVICE_RESOURCE,
+	[BLK_STS_IOERR]		= NOTIFY_BLOCK_ERROR_IO,
+};
+#endif
+
 blk_status_t errno_to_blk_status(int errno)
 {
 	int i;
@@ -221,6 +237,19 @@ static void print_req_error(struct request *req, blk_status_t status,
 		req->cmd_flags & ~REQ_OP_MASK,
 		req->nr_phys_segments,
 		IOPRIO_PRIO_CLASS(req->ioprio));
+
+#ifdef CONFIG_BLK_NOTIFICATIONS
+	if (blk_notifications[idx]) {
+		struct block_notification n = {
+			.watch.type	= WATCH_TYPE_BLOCK_NOTIFY,
+			.watch.subtype	= blk_notifications[idx],
+			.watch.info	= watch_sizeof(n),
+			.dev		= req->rq_disk ? disk_devt(req->rq_disk) : 0,
+			.sector		= blk_rq_pos(req),
+		};
+		post_block_notification(&n);
+	}
+#endif
 }
 
 static void req_bio_endio(struct request *rq, struct bio *bio,
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 1ef375dafb1c..5d856f670a8f 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -27,6 +27,7 @@
 #include <linux/percpu-refcount.h>
 #include <linux/scatterlist.h>
 #include <linux/blkzoned.h>
+#include <linux/watch_queue.h>
 
 struct module;
 struct scsi_ioctl_command;
@@ -1742,6 +1743,20 @@ static inline bool blk_req_can_dispatch_to_zone(struct request *rq)
 }
 #endif /* CONFIG_BLK_DEV_ZONED */
 
+#ifdef CONFIG_BLK_NOTIFICATIONS
+static inline void post_block_notification(struct block_notification *n)
+{
+	u64 id = 0; /* Might want to allow dev# here. */
+
+	post_device_notification(&n->watch, id);
+}
+#else
+static inline void post_block_notification(struct block_notification *n)
+{
+}
+#endif
+
+
 #else /* CONFIG_BLOCK */
 
 struct block_device;
diff --git a/include/uapi/linux/watch_queue.h b/include/uapi/linux/watch_queue.h
index 654d4ba8b909..9a6c059af09d 100644
--- a/include/uapi/linux/watch_queue.h
+++ b/include/uapi/linux/watch_queue.h
@@ -11,7 +11,8 @@
 enum watch_notification_type {
 	WATCH_TYPE_META		= 0,	/* Special record */
 	WATCH_TYPE_KEY_NOTIFY	= 1,	/* Key change event notification */
-	WATCH_TYPE___NR		= 2
+	WATCH_TYPE_BLOCK_NOTIFY	= 2,	/* Block layer event notification */
+	WATCH_TYPE___NR		= 3
 };
 
 enum watch_meta_notification_subtype {
@@ -124,4 +125,31 @@ struct key_notification {
 	__u32	aux;		/* Per-type auxiliary data */
 };
 
+/*
+ * Type of block layer notification.
+ */
+enum block_notification_type {
+	NOTIFY_BLOCK_ERROR_TIMEOUT		= 1, /* Timeout error */
+	NOTIFY_BLOCK_ERROR_NO_SPACE		= 2, /* Critical space allocation error */
+	NOTIFY_BLOCK_ERROR_RECOVERABLE_TRANSPORT = 3, /* Recoverable transport error */
+	NOTIFY_BLOCK_ERROR_CRITICAL_TARGET	= 4, /* Critical target error */
+	NOTIFY_BLOCK_ERROR_CRITICAL_NEXUS	= 5, /* Critical nexus error */
+	NOTIFY_BLOCK_ERROR_CRITICAL_MEDIUM	= 6, /* Critical medium error */
+	NOTIFY_BLOCK_ERROR_PROTECTION		= 7, /* Protection error */
+	NOTIFY_BLOCK_ERROR_KERNEL_RESOURCE	= 8, /* Kernel resource error */
+	NOTIFY_BLOCK_ERROR_DEVICE_RESOURCE	= 9, /* Device resource error */
+	NOTIFY_BLOCK_ERROR_IO			= 10, /* Other I/O error */
+};
+
+/*
+ * Block layer notification record.
+ * - watch.type = WATCH_TYPE_BLOCK_NOTIFY
+ * - watch.subtype = enum block_notification_type
+ */
+struct block_notification {
+	struct watch_notification watch; /* WATCH_TYPE_BLOCK_NOTIFY */
+	__u64	dev;			/* Device number */
+	__u64	sector;			/* Affected sector */
+};
+
 #endif /* _UAPI_LINUX_WATCH_QUEUE_H */

  parent reply	other threads:[~2019-08-30 13:58 UTC|newest]

Thread overview: 234+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20190903085706.7700-1-hdanton@sina.com>
2019-08-30 13:57 ` [PATCH 00/11] Keyrings, Block and USB notifications [ver #7] David Howells
2019-08-30 13:57   ` David Howells
2019-08-30 13:57   ` David Howells
2019-08-30 13:57   ` [PATCH 01/11] uapi: General notification ring definitions " David Howells
2019-08-30 13:57     ` David Howells
2019-08-30 13:57     ` David Howells
2019-08-30 13:57   ` [PATCH 02/11] security: Add hooks to rule on setting a watch " David Howells
2019-08-30 13:57     ` David Howells
2019-08-30 13:57     ` David Howells
2019-08-30 13:57   ` [PATCH 03/11] security: Add a hook for the point of notification insertion " David Howells
2019-08-30 13:57     ` David Howells
2019-08-30 13:57     ` David Howells
2019-08-30 13:57   ` [PATCH 04/11] General notification queue with user mmap()'able ring buffer " David Howells
2019-08-30 13:57     ` David Howells
2019-08-30 13:57     ` David Howells
2019-08-30 13:57   ` [PATCH 05/11] keys: Add a notification facility " David Howells
2019-08-30 13:57     ` David Howells
2019-08-30 13:57     ` David Howells
2019-08-30 13:58   ` [PATCH 06/11] Add a general, global device notification watch list " David Howells
2019-08-30 13:58     ` David Howells
2019-08-30 13:58     ` David Howells
2019-09-03  8:34     ` Yoshihiro Shimoda
2019-09-03  8:34       ` Yoshihiro Shimoda
2019-09-03  8:34       ` Yoshihiro Shimoda
2019-09-03 16:41     ` David Howells
2019-09-03 16:41       ` David Howells
2019-09-03 16:41       ` David Howells
2019-08-30 13:58   ` David Howells [this message]
2019-08-30 13:58     ` [PATCH 07/11] block: Add block layer notifications " David Howells
2019-08-30 13:58     ` David Howells
2019-08-30 13:58   ` [PATCH 08/11] usb: Add USB subsystem " David Howells
2019-08-30 13:58     ` David Howells
2019-08-30 13:58     ` David Howells
2019-09-03  8:53     ` Yoshihiro Shimoda
2019-09-03  8:53       ` Yoshihiro Shimoda
2019-09-03  8:53       ` Yoshihiro Shimoda
2019-09-03  9:37       ` Greg Kroah-Hartman
2019-09-03  9:37         ` Greg Kroah-Hartman
2019-09-03  9:37         ` Greg Kroah-Hartman
2019-09-04  1:53         ` Yoshihiro Shimoda
2019-09-04  1:53           ` Yoshihiro Shimoda
2019-09-04  1:53           ` Yoshihiro Shimoda
2019-09-03 12:51     ` Guenter Roeck
2019-09-03 12:51       ` Guenter Roeck
2019-09-03 16:07     ` David Howells
2019-09-03 16:07       ` David Howells
2019-09-03 16:12       ` Guenter Roeck
2019-09-03 16:12         ` Guenter Roeck
2019-09-03 16:29       ` David Howells
2019-09-03 16:29         ` David Howells
2019-09-03 17:06         ` Alan Stern
2019-09-03 17:06           ` Alan Stern
2019-09-03 17:06           ` Alan Stern
2019-09-03 17:17           ` Alan Stern
2019-09-03 17:17             ` Alan Stern
2019-09-03 17:17             ` Alan Stern
2019-09-04 15:17             ` David Howells
2019-09-04 15:17               ` David Howells
2019-08-30 13:58   ` [PATCH 09/11] Add sample notification program " David Howells
2019-08-30 13:58     ` David Howells
2019-08-30 13:58     ` David Howells
2019-08-30 13:58   ` [PATCH 10/11] selinux: Implement the watch_key security hook " David Howells
2019-08-30 13:58     ` David Howells
2019-08-30 13:58     ` David Howells
2019-08-30 14:15     ` Stephen Smalley
2019-08-30 14:15       ` Stephen Smalley
2019-08-30 14:23     ` David Howells
2019-08-30 14:23       ` David Howells
2019-08-30 14:41     ` David Howells
2019-08-30 14:41       ` David Howells
2019-08-30 15:41       ` Stephen Smalley
2019-08-30 15:41         ` Stephen Smalley
2019-08-30 13:58   ` [PATCH 11/11] smack: Implement the watch_key and post_notification hooks [untested] " David Howells
2019-08-30 13:58     ` David Howells
2019-08-30 13:58     ` David Howells
2019-09-03 15:20     ` Casey Schaufler
2019-09-03 15:20       ` Casey Schaufler
2019-09-03 15:41     ` David Howells
2019-09-03 15:41       ` David Howells
2019-09-03 17:40       ` Casey Schaufler
2019-09-03 17:40         ` Casey Schaufler
2019-09-03 18:06       ` David Howells
2019-09-03 18:06         ` David Howells
2019-09-03 22:16         ` Casey Schaufler
2019-09-03 22:16           ` Casey Schaufler
2019-09-03 22:39         ` David Howells
2019-09-03 22:39           ` David Howells
2019-09-04 12:08         ` David Howells
2019-09-04 12:08           ` David Howells
2019-09-04 14:56           ` Casey Schaufler
2019-09-04 14:56             ` Casey Schaufler
2019-08-30 14:15   ` watch_queue(7) manpage David Howells
2019-08-30 14:15     ` David Howells
2019-08-30 14:15     ` David Howells
2019-08-30 14:15   ` watch_devices(2) manpage David Howells
2019-08-30 14:15     ` David Howells
2019-08-30 14:16   ` keyctl_watch_key.3 manpage David Howells
2019-08-30 14:16     ` David Howells
2019-08-30 22:09   ` [PATCH 00/11] Keyrings, Block and USB notifications [ver #7] Casey Schaufler
2019-08-30 22:09     ` Casey Schaufler
2019-09-02 12:39   ` David Howells
2019-09-02 12:39     ` David Howells
2019-09-02 13:26   ` David Howells
2019-09-02 13:26     ` David Howells
2019-09-03 16:06   ` [PATCH 04/11] General notification queue with user mmap()'able ring buffer " David Howells
2019-09-03 16:06     ` David Howells
2019-09-03 16:37   ` David Howells
2019-09-03 16:37     ` David Howells
2019-09-04 22:15 [PATCH 00/11] Keyrings, Block and USB notifications [ver #8] David Howells
2019-09-04 22:15 ` David Howells
2019-09-04 22:15 ` David Howells
2019-09-04 22:15 ` [PATCH 01/11] uapi: General notification ring definitions " David Howells
2019-09-04 22:15   ` David Howells
2019-09-04 22:15   ` David Howells
2019-09-04 22:16 ` [PATCH 02/11] security: Add hooks to rule on setting a watch " David Howells
2019-09-04 22:16   ` David Howells
2019-09-04 22:16   ` David Howells
2019-09-04 22:16 ` [PATCH 03/11] security: Add a hook for the point of notification insertion " David Howells
2019-09-04 22:16   ` David Howells
2019-09-04 22:16   ` David Howells
2019-09-04 22:16 ` [PATCH 04/11] General notification queue with user mmap()'able ring buffer " David Howells
2019-09-04 22:16   ` David Howells
2019-09-04 22:16   ` David Howells
2019-09-04 22:16 ` [PATCH 05/11] keys: Add a notification facility " David Howells
2019-09-04 22:16   ` David Howells
2019-09-04 22:16   ` David Howells
2019-09-04 22:16 ` [PATCH 06/11] Add a general, global device notification watch list " David Howells
2019-09-04 22:16   ` David Howells
2019-09-04 22:16   ` David Howells
2019-09-04 22:16 ` [PATCH 07/11] block: Add block layer notifications " David Howells
2019-09-04 22:16   ` David Howells
2019-09-04 22:16   ` David Howells
2019-09-04 22:16 ` [PATCH 08/11] usb: Add USB subsystem " David Howells
2019-09-04 22:16   ` David Howells
2019-09-04 22:16   ` David Howells
2019-09-04 22:17 ` [PATCH 09/11] Add sample notification program " David Howells
2019-09-04 22:17   ` David Howells
2019-09-04 22:17   ` David Howells
2019-09-04 22:17 ` [PATCH 10/11] selinux: Implement the watch_key security hook " David Howells
2019-09-04 22:17   ` David Howells
2019-09-04 22:17   ` David Howells
2019-09-04 22:17 ` [PATCH 11/11] smack: Implement the watch_key and post_notification hooks " David Howells
2019-09-04 22:17   ` David Howells
2019-09-04 22:17   ` David Howells
2019-09-04 22:28 ` [PATCH 00/11] Keyrings, Block and USB notifications " Linus Torvalds
2019-09-04 22:28   ` Linus Torvalds
2019-09-05 17:01 ` Why add the general notification queue and its sources David Howells
2019-09-05 17:01   ` David Howells
2019-09-05 17:19   ` Linus Torvalds
2019-09-05 17:19     ` Linus Torvalds
2019-09-05 18:32     ` Ray Strode
2019-09-05 18:32       ` Ray Strode
2019-09-05 18:32       ` Ray Strode
2019-09-05 20:39       ` Linus Torvalds
2019-09-05 20:39         ` Linus Torvalds
2019-09-06 19:32         ` Ray Strode
2019-09-06 19:32           ` Ray Strode
2019-09-06 19:41           ` Ray Strode
2019-09-06 19:41             ` Ray Strode
2019-09-06 19:53           ` Robbie Harwood
2019-09-06 19:53             ` Robbie Harwood
2019-09-06 19:53             ` Robbie Harwood
2019-09-05 21:32       ` David Howells
2019-09-05 21:32         ` David Howells
2019-09-05 22:08         ` Linus Torvalds
2019-09-05 22:08           ` Linus Torvalds
2019-09-05 23:18         ` David Howells
2019-09-05 23:18           ` David Howells
2019-09-06  0:07           ` Linus Torvalds
2019-09-06  0:07             ` Linus Torvalds
2019-09-06 10:09           ` David Howells
2019-09-06 10:09             ` David Howells
2019-09-06 15:35             ` Linus Torvalds
2019-09-06 15:35               ` Linus Torvalds
2019-09-06 15:53               ` Linus Torvalds
2019-09-06 15:53                 ` Linus Torvalds
2019-09-06 16:12                 ` Steven Whitehouse
2019-09-06 16:12                   ` Steven Whitehouse
2019-09-06 17:07                   ` Linus Torvalds
2019-09-06 17:07                     ` Linus Torvalds
2019-09-06 17:14                     ` Linus Torvalds
2019-09-06 17:14                       ` Linus Torvalds
2019-09-06 21:19                       ` David Howells
2019-09-06 21:19                         ` David Howells
2019-09-06 17:14                   ` Andy Lutomirski
2019-09-06 17:14                     ` Andy Lutomirski
2019-09-05 18:37     ` Steven Whitehouse
2019-09-05 18:37       ` Steven Whitehouse
2019-09-05 18:51       ` Ray Strode
2019-09-05 18:51         ` Ray Strode
2019-09-05 20:09         ` David Lehman
2019-09-05 20:09           ` David Lehman
2019-09-05 18:33   ` Greg Kroah-Hartman
2019-09-05 18:33     ` Greg Kroah-Hartman
  -- strict thread matches above, loose matches on Subject: below --
2019-08-29 18:29 [PATCH 00/11] Keyrings, Block and USB notifications [ver #6] David Howells
2019-08-29 18:29 ` David Howells
2019-08-29 18:29 ` David Howells
2019-08-29 18:29 ` [PATCH 01/11] uapi: General notification ring definitions " David Howells
2019-08-29 18:29   ` David Howells
2019-08-29 18:29   ` David Howells
2019-08-29 18:30 ` [PATCH 02/11] security: Add hooks to rule on setting a watch " David Howells
2019-08-29 18:30   ` David Howells
2019-08-29 18:30   ` David Howells
2019-08-29 18:30 ` [PATCH 03/11] security: Add a hook for the point of notification insertion " David Howells
2019-08-29 18:30   ` David Howells
2019-08-29 18:30   ` David Howells
2019-08-29 18:30 ` [PATCH 04/11] General notification queue with user mmap()'able ring buffer " David Howells
2019-08-29 18:30   ` David Howells
2019-08-29 18:30   ` David Howells
2019-08-29 18:30 ` [PATCH 05/11] keys: Add a notification facility " David Howells
2019-08-29 18:30   ` David Howells
2019-08-29 18:30   ` David Howells
2019-08-29 18:30 ` [PATCH 06/11] Add a general, global device notification watch list " David Howells
2019-08-29 18:30   ` David Howells
2019-08-29 18:30   ` David Howells
2019-08-29 18:30 ` [PATCH 07/11] block: Add block layer notifications " David Howells
2019-08-29 18:30   ` David Howells
2019-08-29 18:30   ` David Howells
2019-08-29 18:31 ` [PATCH 08/11] usb: Add USB subsystem " David Howells
2019-08-29 18:31   ` David Howells
2019-08-29 18:31   ` David Howells
2019-08-29 18:31 ` [PATCH 09/11] Add sample notification program " David Howells
2019-08-29 18:31   ` David Howells
2019-08-29 18:31   ` David Howells
2019-08-29 18:31 ` [PATCH 10/11] selinux: Implement the watch_key security hook " David Howells
2019-08-29 18:31   ` David Howells
2019-08-29 18:31   ` David Howells
2019-08-29 18:44   ` Stephen Smalley
2019-08-29 18:44     ` Stephen Smalley
2019-08-29 19:11   ` David Howells
2019-08-29 19:11     ` David Howells
2019-08-29 18:31 ` [PATCH 11/11] smack: Implement the watch_key and post_notification hooks [untested] " David Howells
2019-08-29 18:31   ` David Howells
2019-08-29 18:31   ` David Howells

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=156717349477.2204.2264554813509459287.stgit@warthog.procyon.org.uk \
    --to=dhowells@redhat.com \
    --cc=casey@schaufler-ca.com \
    --cc=christian@brauner.io \
    --cc=gregkh@linuxfoundation.org \
    --cc=keyrings@vger.kernel.org \
    --cc=linux-api@vger.kernel.org \
    --cc=linux-block@vger.kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=nicolas.dichtel@6wind.com \
    --cc=raven@themaw.net \
    --cc=sds@tycho.nsa.gov \
    --cc=viro@zeniv.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.