locking/mutex: Introduce devm_mutex_init()
authorGeorge Stark <gnstark@salutedevices.com>
Thu, 11 Apr 2024 16:10:25 +0000 (19:10 +0300)
committerLee Jones <lee@kernel.org>
Thu, 11 Apr 2024 16:34:41 +0000 (17:34 +0100)
Using of devm API leads to a certain order of releasing resources.
So all dependent resources which are not devm-wrapped should be deleted
with respect to devm-release order. Mutex is one of such objects that
often is bound to other resources and has no own devm wrapping.
Since mutex_destroy() actually does nothing in non-debug builds
frequently calling mutex_destroy() is just ignored which is safe for now
but wrong formally and can lead to a problem if mutex_destroy() will be
extended so introduce devm_mutex_init().

Suggested-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Signed-off-by: George Stark <gnstark@salutedevices.com>
Reviewed-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Reviewed-by: Marek BehĂșn <kabel@kernel.org>
Acked-by: Waiman Long <longman@redhat.com>
Link: https://lore.kernel.org/r/20240411161032.609544-2-gnstark@salutedevices.com
Signed-off-by: Lee Jones <lee@kernel.org>
include/linux/mutex.h
kernel/locking/mutex-debug.c

index 67edc4ca2beeb77ece386f70cc81a04526e91704..a561c629d89f0fb7d1cb16ca867e503c4e2c99c2 100644 (file)
@@ -22,6 +22,8 @@
 #include <linux/cleanup.h>
 #include <linux/mutex_types.h>
 
+struct device;
+
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 # define __DEP_MAP_MUTEX_INITIALIZER(lockname)                 \
                , .dep_map = {                                  \
@@ -117,6 +119,31 @@ do {                                                       \
 } while (0)
 #endif /* CONFIG_PREEMPT_RT */
 
+#ifdef CONFIG_DEBUG_MUTEXES
+
+int __devm_mutex_init(struct device *dev, struct mutex *lock);
+
+#else
+
+static inline int __devm_mutex_init(struct device *dev, struct mutex *lock)
+{
+       /*
+        * When CONFIG_DEBUG_MUTEXES is off mutex_destroy() is just a nop so
+        * no really need to register it in the devm subsystem.
+        */
+       return 0;
+}
+
+#endif
+
+#define devm_mutex_init(dev, mutex)                    \
+({                                                     \
+       typeof(mutex) mutex_ = (mutex);                 \
+                                                       \
+       mutex_init(mutex_);                             \
+       __devm_mutex_init(dev, mutex_);                 \
+})
+
 /*
  * See kernel/locking/mutex.c for detailed documentation of these APIs.
  * Also see Documentation/locking/mutex-design.rst.
index bc8abb8549d20d38638ab6e1a10d1107f1fe39af..6e6f6071cfa279584683634c291e6e4c91dc90b2 100644 (file)
@@ -12,6 +12,7 @@
  */
 #include <linux/mutex.h>
 #include <linux/delay.h>
+#include <linux/device.h>
 #include <linux/export.h>
 #include <linux/poison.h>
 #include <linux/sched.h>
@@ -89,6 +90,17 @@ void debug_mutex_init(struct mutex *lock, const char *name,
        lock->magic = lock;
 }
 
+static void devm_mutex_release(void *res)
+{
+       mutex_destroy(res);
+}
+
+int __devm_mutex_init(struct device *dev, struct mutex *lock)
+{
+       return devm_add_action_or_reset(dev, devm_mutex_release, lock);
+}
+EXPORT_SYMBOL_GPL(__devm_mutex_init);
+
 /***
  * mutex_destroy - mark a mutex unusable
  * @lock: the mutex to be destroyed