mirror of
				https://github.com/Ysurac/openmptcprouter.git
				synced 2025-03-09 15:40:20 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			145 lines
		
	
	
	
		
			4 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			145 lines
		
	
	
	
		
			4 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
From e07ace307ce598847074a096f408bec0e3a392ed Mon Sep 17 00:00:00 2001
 | 
						|
From: Daniel Golle <daniel@makrotopia.org>
 | 
						|
Date: Thu, 30 May 2024 03:14:34 +0100
 | 
						|
Subject: [PATCH 3/9] block: add support for notifications
 | 
						|
 | 
						|
Add notifier block to notify other subsystems about the addition or
 | 
						|
removal of block devices.
 | 
						|
 | 
						|
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
 | 
						|
---
 | 
						|
 block/Kconfig          |  6 +++
 | 
						|
 block/Makefile         |  1 +
 | 
						|
 block/blk-notify.c     | 88 ++++++++++++++++++++++++++++++++++++++++++
 | 
						|
 include/linux/blkdev.h |  8 ++++
 | 
						|
 4 files changed, 103 insertions(+)
 | 
						|
 create mode 100644 block/blk-notify.c
 | 
						|
 | 
						|
--- a/block/Kconfig
 | 
						|
+++ b/block/Kconfig
 | 
						|
@@ -208,6 +208,12 @@ config BLK_INLINE_ENCRYPTION_FALLBACK
 | 
						|
 	  by falling back to the kernel crypto API when inline
 | 
						|
 	  encryption hardware is not present.
 | 
						|
 
 | 
						|
+config BLOCK_NOTIFIERS
 | 
						|
+	bool "Enable support for notifications in block layer"
 | 
						|
+	help
 | 
						|
+	  Enable this option to provide notifiers for other subsystems
 | 
						|
+	  upon addition or removal of block devices.
 | 
						|
+
 | 
						|
 source "block/partitions/Kconfig"
 | 
						|
 
 | 
						|
 config BLK_MQ_PCI
 | 
						|
--- a/block/Makefile
 | 
						|
+++ b/block/Makefile
 | 
						|
@@ -40,3 +40,4 @@ obj-$(CONFIG_BLK_INLINE_ENCRYPTION)	+= b
 | 
						|
 					   blk-crypto-sysfs.o
 | 
						|
 obj-$(CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK)	+= blk-crypto-fallback.o
 | 
						|
 obj-$(CONFIG_BLOCK_HOLDER_DEPRECATED)	+= holder.o
 | 
						|
+obj-$(CONFIG_BLOCK_NOTIFIERS) += blk-notify.o
 | 
						|
--- /dev/null
 | 
						|
+++ b/block/blk-notify.c
 | 
						|
@@ -0,0 +1,88 @@
 | 
						|
+// SPDX-License-Identifier: GPL-2.0-or-later
 | 
						|
+/*
 | 
						|
+ * Notifiers for addition and removal of block devices
 | 
						|
+ *
 | 
						|
+ * Copyright (c) 2024 Daniel Golle <daniel@makrotopia.org>
 | 
						|
+ */
 | 
						|
+
 | 
						|
+#include <linux/list.h>
 | 
						|
+#include <linux/mutex.h>
 | 
						|
+#include <linux/notifier.h>
 | 
						|
+
 | 
						|
+#include "blk.h"
 | 
						|
+
 | 
						|
+struct blk_device_list {
 | 
						|
+	struct device *dev;
 | 
						|
+	struct list_head list;
 | 
						|
+};
 | 
						|
+
 | 
						|
+static RAW_NOTIFIER_HEAD(blk_notifier_list);
 | 
						|
+static DEFINE_MUTEX(blk_notifier_lock);
 | 
						|
+static LIST_HEAD(blk_devices);
 | 
						|
+
 | 
						|
+void blk_register_notify(struct notifier_block *nb)
 | 
						|
+{
 | 
						|
+	struct blk_device_list *existing_blkdev;
 | 
						|
+
 | 
						|
+	mutex_lock(&blk_notifier_lock);
 | 
						|
+	raw_notifier_chain_register(&blk_notifier_list, nb);
 | 
						|
+
 | 
						|
+	list_for_each_entry(existing_blkdev, &blk_devices, list)
 | 
						|
+		nb->notifier_call(nb, BLK_DEVICE_ADD, existing_blkdev->dev);
 | 
						|
+
 | 
						|
+	mutex_unlock(&blk_notifier_lock);
 | 
						|
+}
 | 
						|
+EXPORT_SYMBOL_GPL(blk_register_notify);
 | 
						|
+
 | 
						|
+void blk_unregister_notify(struct notifier_block *nb)
 | 
						|
+{
 | 
						|
+	mutex_lock(&blk_notifier_lock);
 | 
						|
+	raw_notifier_chain_unregister(&blk_notifier_list, nb);
 | 
						|
+	mutex_unlock(&blk_notifier_lock);
 | 
						|
+}
 | 
						|
+EXPORT_SYMBOL_GPL(blk_unregister_notify);
 | 
						|
+
 | 
						|
+static int blk_call_notifier_add(struct device *dev)
 | 
						|
+{
 | 
						|
+	struct blk_device_list *new_blkdev;
 | 
						|
+
 | 
						|
+	new_blkdev = kmalloc(sizeof(*new_blkdev), GFP_KERNEL);
 | 
						|
+	if (!new_blkdev)
 | 
						|
+		return -ENOMEM;
 | 
						|
+
 | 
						|
+	new_blkdev->dev = dev;
 | 
						|
+	mutex_lock(&blk_notifier_lock);
 | 
						|
+	list_add_tail(&new_blkdev->list, &blk_devices);
 | 
						|
+	raw_notifier_call_chain(&blk_notifier_list, BLK_DEVICE_ADD, dev);
 | 
						|
+	mutex_unlock(&blk_notifier_lock);
 | 
						|
+
 | 
						|
+	return 0;
 | 
						|
+}
 | 
						|
+
 | 
						|
+static void blk_call_notifier_remove(struct device *dev)
 | 
						|
+{
 | 
						|
+	struct blk_device_list *old_blkdev, *tmp;
 | 
						|
+
 | 
						|
+	mutex_lock(&blk_notifier_lock);
 | 
						|
+	list_for_each_entry_safe(old_blkdev, tmp, &blk_devices, list) {
 | 
						|
+		if (old_blkdev->dev != dev)
 | 
						|
+			continue;
 | 
						|
+
 | 
						|
+		list_del(&old_blkdev->list);
 | 
						|
+		kfree(old_blkdev);
 | 
						|
+	}
 | 
						|
+	raw_notifier_call_chain(&blk_notifier_list, BLK_DEVICE_REMOVE, dev);
 | 
						|
+	mutex_unlock(&blk_notifier_lock);
 | 
						|
+}
 | 
						|
+
 | 
						|
+static struct class_interface blk_notifications_bus_interface __refdata = {
 | 
						|
+	.class = &block_class,
 | 
						|
+	.add_dev = &blk_call_notifier_add,
 | 
						|
+	.remove_dev = &blk_call_notifier_remove,
 | 
						|
+};
 | 
						|
+
 | 
						|
+static int __init blk_notifications_init(void)
 | 
						|
+{
 | 
						|
+	return class_interface_register(&blk_notifications_bus_interface);
 | 
						|
+}
 | 
						|
+device_initcall(blk_notifications_init);
 | 
						|
--- a/include/linux/blkdev.h
 | 
						|
+++ b/include/linux/blkdev.h
 | 
						|
@@ -1564,4 +1564,12 @@ struct io_comp_batch {
 | 
						|
 
 | 
						|
 #define DEFINE_IO_COMP_BATCH(name)	struct io_comp_batch name = { }
 | 
						|
 
 | 
						|
+
 | 
						|
+#ifdef CONFIG_BLOCK_NOTIFIERS
 | 
						|
+#define BLK_DEVICE_ADD		1
 | 
						|
+#define BLK_DEVICE_REMOVE	2
 | 
						|
+void blk_register_notify(struct notifier_block *nb);
 | 
						|
+void blk_unregister_notify(struct notifier_block *nb);
 | 
						|
+#endif
 | 
						|
+
 | 
						|
 #endif /* _LINUX_BLKDEV_H */
 |