kernelnewbies.kernelnewbies.org archive mirror
 help / color / mirror / Atom feed
From: Ian Pilcher <arequipeno@gmail.com>
To: linux-block@vger.kernel.org, linux-leds@vger.kernel.org
Cc: axboe@kernel.dk, Ian Pilcher <arequipeno@gmail.com>,
	linux-kernel@vger.kernel.org, pavel@ucw.cz,
	kernelnewbies@kernelnewbies.org
Subject: [RFC PATCH 6/8] block: Add kernel APIs to set & clear per-block device LED triggers
Date: Wed, 28 Jul 2021 20:53:42 -0500	[thread overview]
Message-ID: <20210729015344.3366750-7-arequipeno@gmail.com> (raw)
In-Reply-To: <20210729015344.3366750-1-arequipeno@gmail.com>

* Clear LED trigger (decrement trigger reference count) when device
  is deleted, e.g. when a USB disk is unplugged.

Signed-off-by: Ian Pilcher <arequipeno@gmail.com>
---
 block/blk-ledtrig.c         | 131 ++++++++++++++++++++++++++++++++++++
 block/blk-ledtrig.h         |   5 ++
 block/genhd.c               |   2 +
 include/linux/blk-ledtrig.h |   5 ++
 4 files changed, 143 insertions(+)

diff --git a/block/blk-ledtrig.c b/block/blk-ledtrig.c
index 6392ab4169f9..7c8fdff88683 100644
--- a/block/blk-ledtrig.c
+++ b/block/blk-ledtrig.c
@@ -348,3 +348,134 @@ void __init blk_ledtrig_init(void)
 init_error_new:
 	pr_err("failed to initialize blkdev LED triggers (%d)\n", ret);
 }
+
+
+/*
+ *
+ *	Set a device trigger
+ *
+ */
+
+static int __blk_ledtrig_set(struct gendisk *const gd, const char *const name,
+			     const size_t name_len)
+{
+	struct blk_ledtrig *t;
+	bool already_set;
+	int ret;
+
+	ret = mutex_lock_interruptible(&blk_ledtrig_list_mutex);
+	if (unlikely(ret != 0))
+		goto set_exit_return;
+
+	t = blk_ledtrig_find(name, name_len);
+	if (t == NULL) {
+		pr_warn("blockdev LED trigger named %.*s doesn't exist\n",
+			(int)name_len, name);
+		ret = -ENODEV;
+		goto set_exit_unlock_list;
+	}
+
+	ret = mutex_lock_interruptible(&t->refcount_mutex);
+	if (unlikely(ret != 0))
+		goto set_exit_unlock_list;
+
+	// Holding the refcount mutex blocks __blk_ledtrig_delete, so we don't
+	// actually need to hold the list mutex anymore, but it makes the flow
+	// much simpler to do so
+
+	if (WARN_ON_ONCE(t->refcount == INT_MAX)) {
+		ret = -ERANGE;
+		goto set_exit_unlock_refcount;
+	}
+
+	ret = mutex_lock_interruptible(&gd->ledtrig_mutex);
+	if (unlikely(ret != 0))
+		goto set_exit_unlock_refcount;
+
+	if (gd->ledtrig == NULL) {
+		already_set = false;
+		gd->ledtrig = t;
+	} else {
+		already_set = true;
+	}
+
+	mutex_unlock(&gd->ledtrig_mutex);
+
+	if (already_set) {
+		pr_warn("blockdev trigger for %s already set\n",
+			gd->disk_name);
+		ret = -EBUSY;
+		goto set_exit_unlock_refcount;
+	}
+
+	++(t->refcount);
+	ret = 0;
+
+set_exit_unlock_refcount:
+	mutex_unlock(&t->refcount_mutex);
+set_exit_unlock_list:
+	mutex_unlock(&blk_ledtrig_list_mutex);
+set_exit_return:
+	return ret;
+}
+
+/**
+ * blk_ledtrig_set() - set the LED trigger for a block device
+ * @gd: the block device
+ * @name: the name of the LED trigger
+ *
+ * Context: Process context (can sleep).  Takes and releases
+ *	    @blk_ledtrig_list_mutex, trigger's @refcount_mutex,
+ *	    and @gd->ledtrig_mutex.
+ *
+ * Return: 0 on success; -@errno on error
+ */
+int blk_ledtrig_set(struct gendisk *const gd, const char *const name)
+{
+	return __blk_ledtrig_set(gd, name, strlen(name));
+}
+EXPORT_SYMBOL_GPL(blk_ledtrig_set);
+
+
+/*
+ *
+ *	Clear a device trigger
+ *
+ */
+
+/**
+ * blk_ledtrig_clear() - clear the LED trigger of a block device
+ * @gd: the block device
+ *
+ * Context: Process context (can sleep).  Takes and releases
+ *	    @gd->ledtrig_mutex and @gd->ledtrig->refcount_mutex.
+ *
+ * Return: @true if the trigger was actually cleared; @false if it wasn't set
+ */
+bool blk_ledtrig_clear(struct gendisk *const gd)
+{
+	struct blk_ledtrig *t;
+	bool changed;
+	int new_refcount;
+
+	mutex_lock(&gd->ledtrig_mutex);
+
+	t = gd->ledtrig;
+	if (t == NULL) {
+		changed = false;
+		goto clear_exit_unlock_ledtrig;
+	}
+
+	mutex_lock(&t->refcount_mutex);
+	new_refcount = --(t->refcount);
+	mutex_unlock(&t->refcount_mutex);
+
+	gd->ledtrig = NULL;
+	changed = true;
+
+clear_exit_unlock_ledtrig:
+	mutex_unlock(&gd->ledtrig_mutex);
+	WARN_ON(changed && (new_refcount < 0));
+	return changed;
+}
+EXPORT_SYMBOL_GPL(blk_ledtrig_clear);
diff --git a/block/blk-ledtrig.h b/block/blk-ledtrig.h
index 5854b21a210c..9b718d45783f 100644
--- a/block/blk-ledtrig.h
+++ b/block/blk-ledtrig.h
@@ -24,6 +24,11 @@ static inline void blk_ledtrig_disk_init(struct gendisk *const gd)
 static inline void blk_ledtrig_init(void) {}
 static inline void blk_ledtrig_disk_init(const struct gendisk *gd) {}
 
+// Real function (declared in include/linux/blk-ledtrig.h) returns a bool.
+// This is only here for del_gendisk() (in genhd.c), which doesn't check
+// the return value.
+static inline void blk_ledtrig_clear(const struct gendisk *gd) {}
+
 #endif	// CONFIG_BLK_LED_TRIGGERS
 
 #endif	// _BLOCK_BLK_LEDTRIG_H
diff --git a/block/genhd.c b/block/genhd.c
index 420325447c5d..fb1617f21d79 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -24,6 +24,7 @@
 #include <linux/log2.h>
 #include <linux/pm_runtime.h>
 #include <linux/badblocks.h>
+#include <linux/blk-ledtrig.h>
 
 #include "blk.h"
 #include "blk-ledtrig.h"
@@ -583,6 +584,7 @@ void del_gendisk(struct gendisk *disk)
 	if (WARN_ON_ONCE(!disk->queue))
 		return;
 
+	blk_ledtrig_clear(disk);
 	blk_integrity_del(disk);
 	disk_del_events(disk);
 
diff --git a/include/linux/blk-ledtrig.h b/include/linux/blk-ledtrig.h
index 6f73635f65ec..4ab4658df280 100644
--- a/include/linux/blk-ledtrig.h
+++ b/include/linux/blk-ledtrig.h
@@ -11,8 +11,13 @@
 
 #ifdef CONFIG_BLK_LED_TRIGGERS
 
+#include <linux/genhd.h>
+#include <linux/types.h>
+
 int blk_ledtrig_create(const char *name);
 int blk_ledtrig_delete(const char *name);
+int blk_ledtrig_set(struct gendisk *const gd, const char *const name);
+bool blk_ledtrig_clear(struct gendisk *const gd);
 
 #endif	// CONFIG_BLK_LED_TRIGGERS
 
-- 
2.31.1


_______________________________________________
Kernelnewbies mailing list
Kernelnewbies@kernelnewbies.org
https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies

  parent reply	other threads:[~2021-07-29  1:58 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-29  1:53 [RFC PATCH 0/8] Add configurable block device LED triggers Ian Pilcher
2021-07-29  1:53 ` [RFC PATCH 1/8] docs: Add block device LED trigger documentation Ian Pilcher
2021-07-29  3:09   ` Valdis Klētnieks
2021-07-29 15:52     ` Ian Pilcher
2021-07-30  5:22       ` Greg KH
2021-07-29  5:53   ` Greg KH
2021-07-29 11:59   ` Marek Behún
2021-07-29 18:03     ` Ian Pilcher
2021-07-29  1:53 ` [RFC PATCH 2/8] block: Add block device LED trigger list Ian Pilcher
2021-07-29  3:14   ` Valdis Klētnieks
2021-07-29 15:55     ` Ian Pilcher
2021-07-29  1:53 ` [RFC PATCH 3/8] block: Add kernel APIs to create & delete block device LED triggers Ian Pilcher
2021-07-29  3:45   ` Valdis Klētnieks
2021-07-29 16:16     ` Ian Pilcher
2021-07-29  5:52   ` Greg KH
2021-07-29  1:53 ` [RFC PATCH 4/8] block: Add block class attributes to manage LED trigger list Ian Pilcher
2021-07-29  5:54   ` Greg KH
2021-07-29  1:53 ` [RFC PATCH 5/8] block: Add block device LED trigger info to struct genhd Ian Pilcher
2021-07-29  1:53 ` Ian Pilcher [this message]
2021-07-29  1:53 ` [RFC PATCH 7/8] block: Add block device attributes to set & clear LED triggers Ian Pilcher
2021-07-29  1:53 ` [RFC PATCH 8/8] block: Blink device LED when request is sent to low-level driver Ian Pilcher
2021-07-29  8:54 ` [RFC PATCH 0/8] Add configurable block device LED triggers Pavel Machek
2021-07-29 17:03   ` Ian Pilcher
2021-07-29 18:35     ` Pavel Machek
2021-07-29 19:14       ` Ian Pilcher

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=20210729015344.3366750-7-arequipeno@gmail.com \
    --to=arequipeno@gmail.com \
    --cc=axboe@kernel.dk \
    --cc=kernelnewbies@kernelnewbies.org \
    --cc=linux-block@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-leds@vger.kernel.org \
    --cc=pavel@ucw.cz \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).