Switch to use a linked list instead of dynamic array which makes allocation of kdb macro and traversing the kdb macro commands list simpler.
Also, rename defcmd_set struct to kdb_macro_t struct as it sounds more appropriate given its purpose. Along with this directly embed kdbtab_t struct instead of custom command fields in kdb_macro_t struct as its now possible to register pre-allocated kdb commands via kdb_register_table(). Suggested-by: Daniel Thompson <daniel.thomp...@linaro.org> Signed-off-by: Sumit Garg <sumit.g...@linaro.org> --- Changes in v2: - Define new structs: kdb_macro_t and kdb_macro_cmd_t instead of modifying existing kdb command struct and struct kdb_subcmd. - Reword commit message. kernel/debug/kdb/kdb_main.c | 158 +++++++++++++++++++----------------- 1 file changed, 83 insertions(+), 75 deletions(-) diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c index 9d69169582c6..2f2c0e3b39a9 100644 --- a/kernel/debug/kdb/kdb_main.c +++ b/kernel/debug/kdb/kdb_main.c @@ -678,16 +678,17 @@ static void kdb_cmderror(int diag) * Returns: * zero for success, a kdb diagnostic if error */ -struct defcmd_set { - int count; - bool usable; - char *name; - char *usage; - char *help; - char **command; +struct kdb_macro_t { + kdbtab_t cmd; /* Macro command name */ + struct list_head commands; /* Associated command list */ }; -static struct defcmd_set *defcmd_set; -static int defcmd_set_count; + +struct kdb_macro_cmd_t { + char *cmd; /* Command name */ + struct list_head list_node; /* Command list node */ +}; + +static struct kdb_macro_t *kdb_macro; static bool defcmd_in_progress; /* Forward references */ @@ -695,53 +696,56 @@ static int kdb_exec_defcmd(int argc, const char **argv); static int kdb_defcmd2(const char *cmdstr, const char *argv0) { - struct defcmd_set *s = defcmd_set + defcmd_set_count - 1; - char **save_command = s->command; + struct kdb_macro_cmd_t *kmc; + + if (!kdb_macro) + return KDB_NOTIMP; + if (strcmp(argv0, "endefcmd") == 0) { defcmd_in_progress = false; - if (!s->count) - s->usable = false; - if (s->usable) - /* macros are always safe because when executed each - * internal command re-enters kdb_parse() and is - * safety checked individually. - */ - kdb_register_flags(s->name, kdb_exec_defcmd, s->usage, - s->help, 0, - KDB_ENABLE_ALWAYS_SAFE); + if (!list_empty(&kdb_macro->commands)) + kdb_register_table(&kdb_macro->cmd, 1); return 0; } - if (!s->usable) - return KDB_NOTIMP; - s->command = kcalloc(s->count + 1, sizeof(*(s->command)), GFP_KDB); - if (!s->command) { - kdb_printf("Could not allocate new kdb_defcmd table for %s\n", + + kmc = kmalloc(sizeof(*kmc), GFP_KDB); + if (!kmc) { + kdb_printf("Could not allocate new kdb macro command: %s\n", cmdstr); - s->usable = false; return KDB_NOTIMP; } - memcpy(s->command, save_command, s->count * sizeof(*(s->command))); - s->command[s->count++] = kdb_strdup(cmdstr, GFP_KDB); - kfree(save_command); + + kmc->cmd = kdb_strdup(cmdstr, GFP_KDB); + list_add_tail(&kmc->list_node, &kdb_macro->commands); + return 0; } static int kdb_defcmd(int argc, const char **argv) { - struct defcmd_set *save_defcmd_set = defcmd_set, *s; + kdbtab_t *mp; + if (defcmd_in_progress) { kdb_printf("kdb: nested defcmd detected, assuming missing " "endefcmd\n"); kdb_defcmd2("endefcmd", "endefcmd"); } if (argc == 0) { - int i; - for (s = defcmd_set; s < defcmd_set + defcmd_set_count; ++s) { - kdb_printf("defcmd %s \"%s\" \"%s\"\n", s->name, - s->usage, s->help); - for (i = 0; i < s->count; ++i) - kdb_printf("%s", s->command[i]); - kdb_printf("endefcmd\n"); + kdbtab_t *kp; + struct kdb_macro_t *kmp; + struct kdb_macro_cmd_t *kmc; + + list_for_each_entry(kp, &kdb_cmds_head, list_node) { + if (kp->cmd_func == kdb_exec_defcmd) { + kdb_printf("defcmd %s \"%s\" \"%s\"\n", + kp->cmd_name, kp->cmd_usage, + kp->cmd_help); + kmp = container_of(kp, struct kdb_macro_t, cmd); + list_for_each_entry(kmc, &kmp->commands, + list_node) + kdb_printf("%s", kmc->cmd); + kdb_printf("endefcmd\n"); + } } return 0; } @@ -751,45 +755,43 @@ static int kdb_defcmd(int argc, const char **argv) kdb_printf("Command only available during kdb_init()\n"); return KDB_NOTIMP; } - defcmd_set = kmalloc_array(defcmd_set_count + 1, sizeof(*defcmd_set), - GFP_KDB); - if (!defcmd_set) + kdb_macro = kzalloc(sizeof(*kdb_macro), GFP_KDB); + if (!kdb_macro) goto fail_defcmd; - memcpy(defcmd_set, save_defcmd_set, - defcmd_set_count * sizeof(*defcmd_set)); - s = defcmd_set + defcmd_set_count; - memset(s, 0, sizeof(*s)); - s->usable = true; - s->name = kdb_strdup(argv[1], GFP_KDB); - if (!s->name) + mp = &kdb_macro->cmd; + + mp->cmd_func = kdb_exec_defcmd; + mp->cmd_minlen = 0; + mp->cmd_flags = KDB_ENABLE_ALWAYS_SAFE; + mp->cmd_name = kdb_strdup(argv[1], GFP_KDB); + if (!mp->cmd_name) goto fail_name; - s->usage = kdb_strdup(argv[2], GFP_KDB); - if (!s->usage) + mp->cmd_usage = kdb_strdup(argv[2], GFP_KDB); + if (!mp->cmd_usage) goto fail_usage; - s->help = kdb_strdup(argv[3], GFP_KDB); - if (!s->help) + mp->cmd_help = kdb_strdup(argv[3], GFP_KDB); + if (!mp->cmd_help) goto fail_help; - if (s->usage[0] == '"') { - strcpy(s->usage, argv[2]+1); - s->usage[strlen(s->usage)-1] = '\0'; + if (mp->cmd_usage[0] == '"') { + strcpy(mp->cmd_usage, argv[2]+1); + mp->cmd_usage[strlen(mp->cmd_usage)-1] = '\0'; } - if (s->help[0] == '"') { - strcpy(s->help, argv[3]+1); - s->help[strlen(s->help)-1] = '\0'; + if (mp->cmd_help[0] == '"') { + strcpy(mp->cmd_help, argv[3]+1); + mp->cmd_help[strlen(mp->cmd_help)-1] = '\0'; } - ++defcmd_set_count; + + INIT_LIST_HEAD(&kdb_macro->commands); defcmd_in_progress = true; - kfree(save_defcmd_set); return 0; fail_help: - kfree(s->usage); + kfree(mp->cmd_usage); fail_usage: - kfree(s->name); + kfree(mp->cmd_name); fail_name: - kfree(defcmd_set); + kfree(kdb_macro); fail_defcmd: - kdb_printf("Could not allocate new defcmd_set entry for %s\n", argv[1]); - defcmd_set = save_defcmd_set; + kdb_printf("Could not allocate new kdb_macro entry for %s\n", argv[1]); return KDB_NOTIMP; } @@ -804,25 +806,31 @@ static int kdb_defcmd(int argc, const char **argv) */ static int kdb_exec_defcmd(int argc, const char **argv) { - int i, ret; - struct defcmd_set *s; + int ret; + kdbtab_t *kp; + struct kdb_macro_t *kmp; + struct kdb_macro_cmd_t *kmc; + if (argc != 0) return KDB_ARGCOUNT; - for (s = defcmd_set, i = 0; i < defcmd_set_count; ++i, ++s) { - if (strcmp(s->name, argv[0]) == 0) + + list_for_each_entry(kp, &kdb_cmds_head, list_node) { + if (strcmp(kp->cmd_name, argv[0]) == 0) break; } - if (i == defcmd_set_count) { + if (list_entry_is_head(kp, &kdb_cmds_head, list_node)) { kdb_printf("kdb_exec_defcmd: could not find commands for %s\n", argv[0]); return KDB_NOTIMP; } - for (i = 0; i < s->count; ++i) { - /* Recursive use of kdb_parse, do not use argv after - * this point */ + kmp = container_of(kp, struct kdb_macro_t, cmd); + list_for_each_entry(kmc, &kmp->commands, list_node) { + /* + * Recursive use of kdb_parse, do not use argv after this point. + */ argv = NULL; - kdb_printf("[%s]kdb> %s\n", s->name, s->command[i]); - ret = kdb_parse(s->command[i]); + kdb_printf("[%s]kdb> %s\n", kmp->cmd.cmd_name, kmc->cmd); + ret = kdb_parse(kmc->cmd); if (ret) return ret; } -- 2.25.1 _______________________________________________ Kgdb-bugreport mailing list Kgdb-bugreport@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/kgdb-bugreport