us_manager: add debugging to swap_dcache 33/191033/4
authorVyacheslav Cherkashin <v.cherkashin@samsung.com>
Wed, 3 Oct 2018 11:49:19 +0000 (14:49 +0300)
committerVyacheslav Cherkashin <v.cherkashin@samsung.com>
Fri, 12 Oct 2018 12:47:50 +0000 (15:47 +0300)
For enabling dcache debug, set "#define SWAP_DCACHE_DEBUG"

Sample debugging output:
  SWAP_DCACHE: BUG: incorrect dentry[f5c4f000 ld-2.24.so] counter=2:
  SWAP_DCACHE:     DGET swap_loader[/home/abuild/rpmbuild/BUILD/swap-modules-3.0/modules/loader/loader_storage.c:120]
  SWAP_DCACHE:     DGET swap_preload[/home/abuild/rpmbuild/BUILD/swap-modules-3.0/modules/preload/preload_control.c:253]
  SWAP_DCACHE:     DGET swap_gtp[/home/abuild/rpmbuild/BUILD/swap-modules-3.0/modules/got_patcher/gt_module.c:668]
  SWAP_DCACHE:     DGET swap_gtp[/home/abuild/rpmbuild/BUILD/swap-modules-3.0/modules/got_patcher/gt_module.c:678]
  SWAP_DCACHE:     DPUT swap_preload[/home/abuild/rpmbuild/BUILD/swap-modules-3.0/modules/preload/preload_control.c:90]
  SWAP_DCACHE:     DGET swap_us_manager[/home/abuild/rpmbuild/BUILD/swap-modules-3.0/modules/us_manager/img/img_file.c:57]
  SWAP_DCACHE:     DPUT swap_us_manager[/home/abuild/rpmbuild/BUILD/swap-modules-3.0/modules/us_manager/img/img_file.c:83]
  SWAP_DCACHE:     DGET swap_us_manager[/home/abuild/rpmbuild/BUILD/swap-modules-3.0/modules/us_manager/img/img_file.c:57]
  SWAP_DCACHE:     DPUT swap_us_manager[/home/abuild/rpmbuild/BUILD/swap-modules-3.0/modules/us_manager/img/img_file.c:83]
  SWAP_DCACHE:     DPUT swap_loader[/home/abuild/rpmbuild/BUILD/swap-modules-3.0/modules/loader/loader_storage.c:145]
  SWAP_DCACHE: BUG: incorrect dentry[f5c4f700 libpthread-2.24.so] counter=2:
  SWAP_DCACHE:     DGET swap_preload[/home/abuild/rpmbuild/BUILD/swap-modules-3.0/modules/preload/preload_control.c:253]
  SWAP_DCACHE:     DGET swap_preload[/home/abuild/rpmbuild/BUILD/swap-modules-3.0/modules/preload/preload_process.c:444]
  SWAP_DCACHE:     DGET swap_gtp[/home/abuild/rpmbuild/BUILD/swap-modules-3.0/modules/got_patcher/gt_module.c:979]
  SWAP_DCACHE:     DPUT swap_preload[/home/abuild/rpmbuild/BUILD/swap-modules-3.0/modules/preload/preload_control.c:90]
  SWAP_DCACHE:     DGET swap_us_manager[/home/abuild/rpmbuild/BUILD/swap-modules-3.0/modules/us_manager/img/img_file.c:57]
  SWAP_DCACHE:     DPUT swap_us_manager[/home/abuild/rpmbuild/BUILD/swap-modules-3.0/modules/us_manager/img/img_file.c:83]
  SWAP_DCACHE:     DGET swap_us_manager[/home/abuild/rpmbuild/BUILD/swap-modules-3.0/modules/us_manager/img/img_file.c:57]
  SWAP_DCACHE:     DPUT swap_us_manager[/home/abuild/rpmbuild/BUILD/swap-modules-3.0/modules/us_manager/img/img_file.c:83]

Change-Id: Ie03a86cd0373f1090a1dadb326b2067557607aeb
Signed-off-by: Vyacheslav Cherkashin <v.cherkashin@samsung.com>
modules/us_manager/swap_dcache.c
modules/us_manager/swap_dcache.h

index 6392164e840b7c2c3fa1d1586c8a8ad74d0493e2..bd071c45ebe6caa3969ceb85fee87d7409c24f48 100644 (file)
  */
 
 
+#define pr_fmt(fmt) "SWAP_DCACHE: " fmt
+
 #include <linux/dcache.h>
 #include <linux/namei.h>
 #include "swap_dcache.h"
 
 
-static atomic_t g_counter = ATOMIC_INIT(0);
-
-
-struct dentry *swap_dget_by_path(const char *filepath)
+static struct dentry *do_dget_by_path(const char *filepath)
 {
        struct path path;
        struct dentry *dentry = NULL;
 
        if (kern_path(filepath, LOOKUP_FOLLOW, &path) == 0) {
-               dentry = swap_dget(path.dentry);
+               dentry = dget(path.dentry);
                path_put(&path);
        }
 
        return dentry;
 }
+
+
+#ifndef SWAP_DCACHE_DEBUG
+
+static atomic_t g_counter = ATOMIC_INIT(0);
+
+
+struct dentry *swap_dget_by_path(const char *filepath)
+{
+       struct dentry *dentry = do_dget_by_path(filepath);
+       if (dentry)
+               atomic_inc(&g_counter);
+
+       return dentry;
+}
 EXPORT_SYMBOL_GPL(swap_dget_by_path);
 
 struct dentry *swap_dget(struct dentry *dentry)
@@ -74,3 +88,185 @@ void swap_dentry_uninit(void)
        WARN(counter, "Incorrect dentry usage, counter=%d", counter);
        BUG_ON(counter < 0);
 }
+
+
+#else /* SWAP_DCACHE_DEBUG */
+
+
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+
+struct ddata {
+       struct list_head list;
+
+       struct dentry *dentry;
+       const char *module;
+       const char *file;
+       int line;
+
+       bool is_get;
+};
+
+
+static DEFINE_SPINLOCK(ddata_lock);
+static LIST_HEAD(ddata_head);
+
+
+static void add_to_list(struct dentry *dentry, bool is_get,
+                       const char *module, const char *file, int line)
+{
+       unsigned long flags;
+       struct ddata *d;
+
+       /* skip dput() if dentry == NULL */
+       if (!dentry && !is_get)
+               return;
+
+       d = kmalloc(sizeof(*d), GFP_KERNEL);
+       BUG_ON(!d);
+
+       INIT_LIST_HEAD(&d->list);
+       d->dentry = dentry;
+       d->module = module;
+       d->file = file;
+       d->line = line;
+       d->is_get = is_get;
+
+       /* add to list */
+       spin_lock_irqsave(&ddata_lock, flags);
+       list_add_tail(&d->list, &ddata_head);
+       spin_unlock_irqrestore(&ddata_lock, flags);
+}
+
+static void free_list(void)
+{
+       struct ddata *d, *tmp;
+       list_for_each_entry_safe(d, tmp, &ddata_head, list) {
+               if (d->is_get)
+                       dput(d->dentry);
+               list_del(&d->list);
+               kfree(d);
+       }
+}
+
+static void show_dentry_status(struct dentry *dentry, struct list_head *head)
+{
+       struct ddata *d;
+       int counter = 0;
+
+       /* check on dput() without dget() */
+       list_for_each_entry(d, head, list) {
+               counter += d->is_get ? 1 : -1;
+               if (counter < 0) {
+                       pr_err("BUG: call dput() without dget() in %s[%s:%d]\n",
+                              d->module, d->file, d->line);
+               }
+       }
+
+       /* check counter */
+       if (counter) {
+               pr_err("BUG: incorrect dentry[%p %s] counter=%d:\n",
+                      dentry, dentry->d_name.name, counter);
+
+               list_for_each_entry(d, head, list) {
+                       pr_err("    %s %s[%s:%d]\n",
+                              d->is_get ? "DGET" : "DPUT",
+                              d->module, d->file, d->line);
+               }
+       }
+}
+
+static void show_status(void)
+{
+       LIST_HEAD(tmp_head);
+
+       while (!list_empty(&ddata_head)) {
+               struct ddata *d, *tmp;
+               struct ddata *test_d;
+               LIST_HEAD(test_head);
+
+               test_d = list_first_entry(&ddata_head, struct ddata, list);
+               list_move_tail(&test_d->list, &test_head);
+
+               list_for_each_entry_safe(d, tmp, &ddata_head, list) {
+                       if (test_d->dentry == d->dentry)
+                               list_move_tail(&d->list, &test_head);
+               }
+
+               show_dentry_status(test_d->dentry, &test_head);
+               list_splice_tail_init(&test_head, &tmp_head);
+       }
+
+       list_splice_tail(&tmp_head, &ddata_head);
+}
+
+static bool is_enable = false;
+
+void check_on_enable(const char *cmd, const char *module,
+                    const char *file, int line)
+{
+       if (!is_enable) {
+               pr_err("BUG: call %s() without initialization %s[%s:%d]\n",
+                      cmd, module, file, line);
+       }
+}
+
+struct dentry *__swap_dget_by_path(const char *filepath,
+                                  const char *module,
+                                  const char *file, int line)
+{
+       struct dentry *dentry;
+
+       check_on_enable("DGET", module, file, line);
+
+       dentry = do_dget_by_path(filepath);
+       if (dentry)
+               add_to_list(dentry, true, module, file, line);
+
+       return dentry;
+}
+EXPORT_SYMBOL_GPL(__swap_dget_by_path);
+
+struct dentry *__swap_dget(struct dentry *dentry,
+                          const char *module,
+                          const char *file, int line)
+{
+       check_on_enable("DGET", module, file, line);
+
+       if (dentry) {
+               dget(dentry);
+               add_to_list(dentry, true, module, file, line);
+       }
+
+       return dentry;
+}
+EXPORT_SYMBOL_GPL(__swap_dget);
+
+void __swap_dput(struct dentry *dentry,
+                const char *module,
+                const char *file, int line)
+{
+       check_on_enable("DPUT", module, file, line);
+
+       if (dentry)
+               add_to_list(dentry, false, module, file, line);
+}
+EXPORT_SYMBOL_GPL(__swap_dput);
+
+int swap_dentry_init(void)
+{
+       is_enable = true;
+       return 0;
+}
+
+void swap_dentry_uninit(void)
+{
+       is_enable = false;
+       show_status();
+       free_list();
+}
+
+
+#endif /* SWAP_DCACHE_DEBUG */
index fd717e1ec97c43be7075350394cc6140daf262bf..ac7aac5a474a3256417fcc5837c1f7b8a7e2244f 100644 (file)
 struct dentry;
 
 
+/*
+ * Set "#define SWAP_DCACHE_DEBUG" for dcache debugging.
+ */
+
+#ifndef SWAP_DCACHE_DEBUG
+
+
 struct dentry *swap_dget_by_path(const char *filepath);
 struct dentry *swap_dget(struct dentry *dentry);
 void swap_dput(struct dentry *dentry);
 
+
+#else /* SWAP_DCACHE_DEBUG */
+
+
+#define swap_dget_by_path(filepath) \
+       __swap_dget_by_path(filepath, KBUILD_MODNAME, __FILE__, __LINE__)
+#define swap_dget(dentry) \
+       __swap_dget(dentry, KBUILD_MODNAME, __FILE__, __LINE__)
+#define swap_dput(dentry) \
+       __swap_dput(dentry, KBUILD_MODNAME, __FILE__, __LINE__)
+
+struct dentry *__swap_dget_by_path(const char *filepath, const char *module,
+                                  const char *file, int line);
+struct dentry *__swap_dget(struct dentry *dentry, const char *module,
+                          const char *file, int line);
+void __swap_dput(struct dentry *dentry, const char *module,
+                const char *file, int line);
+
+
+#endif /* SWAP_DCACHE_DEBUG */
+
+
 int swap_dentry_init(void);
 void swap_dentry_uninit(void);