diff mbox series

[RFC,INTERNAL] kdb: Use linked list instead of static array for commands

Message ID 1610974813-22022-1-git-send-email-sumit.garg@linaro.org
State New
Headers show
Series [RFC,INTERNAL] kdb: Use linked list instead of static array for commands | expand

Commit Message

Sumit Garg Jan. 18, 2021, 1 p.m. UTC
Simplify kdb commands registration via using linked list instead of
static array for commands storage.

Signed-off-by: Sumit Garg <sumit.garg@linaro.org>

---

Hi Daniel,

This is my intial step towards kdb code refactoring. Please do let me
know if I am headed in the right direction.

-Sumit

 kernel/debug/kdb/kdb_main.c    | 78 ++++++++++--------------------------------
 kernel/debug/kdb/kdb_private.h |  1 +
 2 files changed, 20 insertions(+), 59 deletions(-)

-- 
2.7.4

Comments

Daniel Thompson Jan. 19, 2021, 9:50 a.m. UTC | #1
On Mon, Jan 18, 2021 at 06:30:13PM +0530, Sumit Garg wrote:
> Simplify kdb commands registration via using linked list instead of

> static array for commands storage.

> 

> Signed-off-by: Sumit Garg <sumit.garg@linaro.org>

> ---

> 

> Hi Daniel,

> 

> This is my intial step towards kdb code refactoring. Please do let me

> know if I am headed in the right direction.


I take it you're reflecting on the "you did start with the most
difficult kdb change to land" comments?

In that sense, yes. This is along the lines of what I originally
briefed. Basically try to reduce the w.t.f. per minute when reading
sources (and kdb scores highly on that measure).


Daniel.


> 

> -Sumit

> 

>  kernel/debug/kdb/kdb_main.c    | 78 ++++++++++--------------------------------

>  kernel/debug/kdb/kdb_private.h |  1 +

>  2 files changed, 20 insertions(+), 59 deletions(-)

> 

> diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c

> index 930ac1b..93ac0f5 100644

> --- a/kernel/debug/kdb/kdb_main.c

> +++ b/kernel/debug/kdb/kdb_main.c

> @@ -33,6 +33,7 @@

>  #include <linux/kallsyms.h>

>  #include <linux/kgdb.h>

>  #include <linux/kdb.h>

> +#include <linux/list.h>

>  #include <linux/notifier.h>

>  #include <linux/interrupt.h>

>  #include <linux/delay.h>

> @@ -84,15 +85,8 @@ static unsigned int kdb_continue_catastrophic =

>  static unsigned int kdb_continue_catastrophic;

>  #endif

>  

> -/* kdb_commands describes the available commands. */

> -static kdbtab_t *kdb_commands;

> -#define KDB_BASE_CMD_MAX 50

> -static int kdb_max_commands = KDB_BASE_CMD_MAX;

> -static kdbtab_t kdb_base_commands[KDB_BASE_CMD_MAX];

> -#define for_each_kdbcmd(cmd, num)					\

> -	for ((cmd) = kdb_base_commands, (num) = 0;			\

> -	     num < kdb_max_commands;					\

> -	     num++, num == KDB_BASE_CMD_MAX ? cmd = kdb_commands : cmd++)

> +/* kdb_cmds_head describes the available commands. */

> +static LIST_HEAD(kdb_cmds_head);

>  

>  typedef struct _kdbmsg {

>  	int	km_diag;	/* kdb diagnostic */

> @@ -921,7 +915,7 @@ int kdb_parse(const char *cmdstr)

>  	char *cp;

>  	char *cpp, quoted;

>  	kdbtab_t *tp;

> -	int i, escaped, ignore_errors = 0, check_grep = 0;

> +	int escaped, ignore_errors = 0, check_grep = 0;

>  

>  	/*

>  	 * First tokenize the command string.

> @@ -1011,7 +1005,7 @@ int kdb_parse(const char *cmdstr)

>  		++argv[0];

>  	}

>  

> -	for_each_kdbcmd(tp, i) {

> +	list_for_each_entry(tp, &kdb_cmds_head, list_node) {

>  		if (tp->cmd_name) {

>  			/*

>  			 * If this command is allowed to be abbreviated,

> @@ -1037,8 +1031,8 @@ int kdb_parse(const char *cmdstr)

>  	 * few characters of this match any of the known commands.

>  	 * e.g., md1c20 should match md.

>  	 */

> -	if (i == kdb_max_commands) {

> -		for_each_kdbcmd(tp, i) {

> +	if (list_entry_is_head(tp, &kdb_cmds_head, list_node)) {

> +		list_for_each_entry(tp, &kdb_cmds_head, list_node) {

>  			if (tp->cmd_name) {

>  				if (strncmp(argv[0],

>  					    tp->cmd_name,

> @@ -1049,7 +1043,7 @@ int kdb_parse(const char *cmdstr)

>  		}

>  	}

>  

> -	if (i < kdb_max_commands) {

> +	if (!list_entry_is_head(tp, &kdb_cmds_head, list_node)) {

>  		int result;

>  

>  		if (!kdb_check_flags(tp->cmd_flags, kdb_cmd_enabled, argc <= 1))

> @@ -2428,12 +2422,11 @@ static int kdb_kgdb(int argc, const char **argv)

>  static int kdb_help(int argc, const char **argv)

>  {

>  	kdbtab_t *kt;

> -	int i;

>  

>  	kdb_printf("%-15.15s %-20.20s %s\n", "Command", "Usage", "Description");

>  	kdb_printf("-----------------------------"

>  		   "-----------------------------\n");

> -	for_each_kdbcmd(kt, i) {

> +	list_for_each_entry(kt, &kdb_cmds_head, list_node) {

>  		char *space = "";

>  		if (KDB_FLAG(CMD_INTERRUPT))

>  			return 0;

> @@ -2667,13 +2660,9 @@ int kdb_register_flags(char *cmd,

>  		       short minlen,

>  		       kdb_cmdflags_t flags)

>  {

> -	int i;

>  	kdbtab_t *kp;

>  

> -	/*

> -	 *  Brute force method to determine duplicates

> -	 */

> -	for_each_kdbcmd(kp, i) {

> +	list_for_each_entry(kp, &kdb_cmds_head, list_node) {

>  		if (kp->cmd_name && (strcmp(kp->cmd_name, cmd) == 0)) {

>  			kdb_printf("Duplicate kdb command registered: "

>  				"%s, func %px help %s\n", cmd, func, help);

> @@ -2681,35 +2670,10 @@ int kdb_register_flags(char *cmd,

>  		}

>  	}

>  

> -	/*

> -	 * Insert command into first available location in table

> -	 */

> -	for_each_kdbcmd(kp, i) {

> -		if (kp->cmd_name == NULL)

> -			break;

> -	}

> -

> -	if (i >= kdb_max_commands) {

> -		kdbtab_t *new = kmalloc_array(kdb_max_commands -

> -						KDB_BASE_CMD_MAX +

> -						kdb_command_extend,

> -					      sizeof(*new),

> -					      GFP_KDB);

> -		if (!new) {

> -			kdb_printf("Could not allocate new kdb_command "

> -				   "table\n");

> -			return 1;

> -		}

> -		if (kdb_commands) {

> -			memcpy(new, kdb_commands,

> -			  (kdb_max_commands - KDB_BASE_CMD_MAX) * sizeof(*new));

> -			kfree(kdb_commands);

> -		}

> -		memset(new + kdb_max_commands - KDB_BASE_CMD_MAX, 0,

> -		       kdb_command_extend * sizeof(*new));

> -		kdb_commands = new;

> -		kp = kdb_commands + kdb_max_commands - KDB_BASE_CMD_MAX;

> -		kdb_max_commands += kdb_command_extend;

> +	kp = kmalloc(sizeof(*kp), GFP_KDB);

> +	if (!kp) {

> +		kdb_printf("Could not allocate new kdb_command table\n");

> +		return 1;

>  	}

>  

>  	kp->cmd_name   = cmd;

> @@ -2719,6 +2683,8 @@ int kdb_register_flags(char *cmd,

>  	kp->cmd_minlen = minlen;

>  	kp->cmd_flags  = flags;

>  

> +	list_add_tail(&kp->list_node, &kdb_cmds_head);

> +

>  	return 0;

>  }

>  EXPORT_SYMBOL_GPL(kdb_register_flags);

> @@ -2757,15 +2723,15 @@ EXPORT_SYMBOL_GPL(kdb_register);

>   */

>  int kdb_unregister(char *cmd)

>  {

> -	int i;

>  	kdbtab_t *kp;

>  

>  	/*

>  	 *  find the command.

>  	 */

> -	for_each_kdbcmd(kp, i) {

> +	list_for_each_entry(kp, &kdb_cmds_head, list_node) {

>  		if (kp->cmd_name && (strcmp(kp->cmd_name, cmd) == 0)) {

> -			kp->cmd_name = NULL;

> +			list_del(&kp->list_node);

> +			kfree(kp);

>  			return 0;

>  		}

>  	}

> @@ -2778,12 +2744,6 @@ EXPORT_SYMBOL_GPL(kdb_unregister);

>  /* Initialize the kdb command table. */

>  static void __init kdb_inittab(void)

>  {

> -	int i;

> -	kdbtab_t *kp;

> -

> -	for_each_kdbcmd(kp, i)

> -		kp->cmd_name = NULL;

> -

>  	kdb_register_flags("md", kdb_md, "<vaddr>",

>  	  "Display Memory Contents, also mdWcN, e.g. md8c1", 1,

>  	  KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS);

> diff --git a/kernel/debug/kdb/kdb_private.h b/kernel/debug/kdb/kdb_private.h

> index a4281fb..7a4a181 100644

> --- a/kernel/debug/kdb/kdb_private.h

> +++ b/kernel/debug/kdb/kdb_private.h

> @@ -174,6 +174,7 @@ typedef struct _kdbtab {

>  	short    cmd_minlen;		/* Minimum legal # command

>  					 * chars required */

>  	kdb_cmdflags_t cmd_flags;	/* Command behaviour flags */

> +	struct list_head list_node;

>  } kdbtab_t;

>  

>  extern int kdb_bt(int, const char **);	/* KDB display back trace */

> -- 

> 2.7.4
Sumit Garg Jan. 19, 2021, 10:22 a.m. UTC | #2
On Tue, 19 Jan 2021 at 15:20, Daniel Thompson
<daniel.thompson@linaro.org> wrote:
>

> On Mon, Jan 18, 2021 at 06:30:13PM +0530, Sumit Garg wrote:

> > Simplify kdb commands registration via using linked list instead of

> > static array for commands storage.

> >

> > Signed-off-by: Sumit Garg <sumit.garg@linaro.org>

> > ---

> >

> > Hi Daniel,

> >

> > This is my intial step towards kdb code refactoring. Please do let me

> > know if I am headed in the right direction.

>

> I take it you're reflecting on the "you did start with the most

> difficult kdb change to land" comments?


Yeah you took it right.

>

> In that sense, yes. This is along the lines of what I originally

> briefed. Basically try to reduce the w.t.f. per minute when reading

> sources (and kdb scores highly on that measure).

>


Sure, I will continue with this effort.

BTW, would you prefer me to push these code refactoring changes
upstream as they are ready or prefer to prepare a patch-set and then
post upstream collectively?

-Sumit

>

> Daniel.

>

>

> >

> > -Sumit

> >

> >  kernel/debug/kdb/kdb_main.c    | 78 ++++++++++--------------------------------

> >  kernel/debug/kdb/kdb_private.h |  1 +

> >  2 files changed, 20 insertions(+), 59 deletions(-)

> >

> > diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c

> > index 930ac1b..93ac0f5 100644

> > --- a/kernel/debug/kdb/kdb_main.c

> > +++ b/kernel/debug/kdb/kdb_main.c

> > @@ -33,6 +33,7 @@

> >  #include <linux/kallsyms.h>

> >  #include <linux/kgdb.h>

> >  #include <linux/kdb.h>

> > +#include <linux/list.h>

> >  #include <linux/notifier.h>

> >  #include <linux/interrupt.h>

> >  #include <linux/delay.h>

> > @@ -84,15 +85,8 @@ static unsigned int kdb_continue_catastrophic =

> >  static unsigned int kdb_continue_catastrophic;

> >  #endif

> >

> > -/* kdb_commands describes the available commands. */

> > -static kdbtab_t *kdb_commands;

> > -#define KDB_BASE_CMD_MAX 50

> > -static int kdb_max_commands = KDB_BASE_CMD_MAX;

> > -static kdbtab_t kdb_base_commands[KDB_BASE_CMD_MAX];

> > -#define for_each_kdbcmd(cmd, num)                                    \

> > -     for ((cmd) = kdb_base_commands, (num) = 0;                      \

> > -          num < kdb_max_commands;                                    \

> > -          num++, num == KDB_BASE_CMD_MAX ? cmd = kdb_commands : cmd++)

> > +/* kdb_cmds_head describes the available commands. */

> > +static LIST_HEAD(kdb_cmds_head);

> >

> >  typedef struct _kdbmsg {

> >       int     km_diag;        /* kdb diagnostic */

> > @@ -921,7 +915,7 @@ int kdb_parse(const char *cmdstr)

> >       char *cp;

> >       char *cpp, quoted;

> >       kdbtab_t *tp;

> > -     int i, escaped, ignore_errors = 0, check_grep = 0;

> > +     int escaped, ignore_errors = 0, check_grep = 0;

> >

> >       /*

> >        * First tokenize the command string.

> > @@ -1011,7 +1005,7 @@ int kdb_parse(const char *cmdstr)

> >               ++argv[0];

> >       }

> >

> > -     for_each_kdbcmd(tp, i) {

> > +     list_for_each_entry(tp, &kdb_cmds_head, list_node) {

> >               if (tp->cmd_name) {

> >                       /*

> >                        * If this command is allowed to be abbreviated,

> > @@ -1037,8 +1031,8 @@ int kdb_parse(const char *cmdstr)

> >        * few characters of this match any of the known commands.

> >        * e.g., md1c20 should match md.

> >        */

> > -     if (i == kdb_max_commands) {

> > -             for_each_kdbcmd(tp, i) {

> > +     if (list_entry_is_head(tp, &kdb_cmds_head, list_node)) {

> > +             list_for_each_entry(tp, &kdb_cmds_head, list_node) {

> >                       if (tp->cmd_name) {

> >                               if (strncmp(argv[0],

> >                                           tp->cmd_name,

> > @@ -1049,7 +1043,7 @@ int kdb_parse(const char *cmdstr)

> >               }

> >       }

> >

> > -     if (i < kdb_max_commands) {

> > +     if (!list_entry_is_head(tp, &kdb_cmds_head, list_node)) {

> >               int result;

> >

> >               if (!kdb_check_flags(tp->cmd_flags, kdb_cmd_enabled, argc <= 1))

> > @@ -2428,12 +2422,11 @@ static int kdb_kgdb(int argc, const char **argv)

> >  static int kdb_help(int argc, const char **argv)

> >  {

> >       kdbtab_t *kt;

> > -     int i;

> >

> >       kdb_printf("%-15.15s %-20.20s %s\n", "Command", "Usage", "Description");

> >       kdb_printf("-----------------------------"

> >                  "-----------------------------\n");

> > -     for_each_kdbcmd(kt, i) {

> > +     list_for_each_entry(kt, &kdb_cmds_head, list_node) {

> >               char *space = "";

> >               if (KDB_FLAG(CMD_INTERRUPT))

> >                       return 0;

> > @@ -2667,13 +2660,9 @@ int kdb_register_flags(char *cmd,

> >                      short minlen,

> >                      kdb_cmdflags_t flags)

> >  {

> > -     int i;

> >       kdbtab_t *kp;

> >

> > -     /*

> > -      *  Brute force method to determine duplicates

> > -      */

> > -     for_each_kdbcmd(kp, i) {

> > +     list_for_each_entry(kp, &kdb_cmds_head, list_node) {

> >               if (kp->cmd_name && (strcmp(kp->cmd_name, cmd) == 0)) {

> >                       kdb_printf("Duplicate kdb command registered: "

> >                               "%s, func %px help %s\n", cmd, func, help);

> > @@ -2681,35 +2670,10 @@ int kdb_register_flags(char *cmd,

> >               }

> >       }

> >

> > -     /*

> > -      * Insert command into first available location in table

> > -      */

> > -     for_each_kdbcmd(kp, i) {

> > -             if (kp->cmd_name == NULL)

> > -                     break;

> > -     }

> > -

> > -     if (i >= kdb_max_commands) {

> > -             kdbtab_t *new = kmalloc_array(kdb_max_commands -

> > -                                             KDB_BASE_CMD_MAX +

> > -                                             kdb_command_extend,

> > -                                           sizeof(*new),

> > -                                           GFP_KDB);

> > -             if (!new) {

> > -                     kdb_printf("Could not allocate new kdb_command "

> > -                                "table\n");

> > -                     return 1;

> > -             }

> > -             if (kdb_commands) {

> > -                     memcpy(new, kdb_commands,

> > -                       (kdb_max_commands - KDB_BASE_CMD_MAX) * sizeof(*new));

> > -                     kfree(kdb_commands);

> > -             }

> > -             memset(new + kdb_max_commands - KDB_BASE_CMD_MAX, 0,

> > -                    kdb_command_extend * sizeof(*new));

> > -             kdb_commands = new;

> > -             kp = kdb_commands + kdb_max_commands - KDB_BASE_CMD_MAX;

> > -             kdb_max_commands += kdb_command_extend;

> > +     kp = kmalloc(sizeof(*kp), GFP_KDB);

> > +     if (!kp) {

> > +             kdb_printf("Could not allocate new kdb_command table\n");

> > +             return 1;

> >       }

> >

> >       kp->cmd_name   = cmd;

> > @@ -2719,6 +2683,8 @@ int kdb_register_flags(char *cmd,

> >       kp->cmd_minlen = minlen;

> >       kp->cmd_flags  = flags;

> >

> > +     list_add_tail(&kp->list_node, &kdb_cmds_head);

> > +

> >       return 0;

> >  }

> >  EXPORT_SYMBOL_GPL(kdb_register_flags);

> > @@ -2757,15 +2723,15 @@ EXPORT_SYMBOL_GPL(kdb_register);

> >   */

> >  int kdb_unregister(char *cmd)

> >  {

> > -     int i;

> >       kdbtab_t *kp;

> >

> >       /*

> >        *  find the command.

> >        */

> > -     for_each_kdbcmd(kp, i) {

> > +     list_for_each_entry(kp, &kdb_cmds_head, list_node) {

> >               if (kp->cmd_name && (strcmp(kp->cmd_name, cmd) == 0)) {

> > -                     kp->cmd_name = NULL;

> > +                     list_del(&kp->list_node);

> > +                     kfree(kp);

> >                       return 0;

> >               }

> >       }

> > @@ -2778,12 +2744,6 @@ EXPORT_SYMBOL_GPL(kdb_unregister);

> >  /* Initialize the kdb command table. */

> >  static void __init kdb_inittab(void)

> >  {

> > -     int i;

> > -     kdbtab_t *kp;

> > -

> > -     for_each_kdbcmd(kp, i)

> > -             kp->cmd_name = NULL;

> > -

> >       kdb_register_flags("md", kdb_md, "<vaddr>",

> >         "Display Memory Contents, also mdWcN, e.g. md8c1", 1,

> >         KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS);

> > diff --git a/kernel/debug/kdb/kdb_private.h b/kernel/debug/kdb/kdb_private.h

> > index a4281fb..7a4a181 100644

> > --- a/kernel/debug/kdb/kdb_private.h

> > +++ b/kernel/debug/kdb/kdb_private.h

> > @@ -174,6 +174,7 @@ typedef struct _kdbtab {

> >       short    cmd_minlen;            /* Minimum legal # command

> >                                        * chars required */

> >       kdb_cmdflags_t cmd_flags;       /* Command behaviour flags */

> > +     struct list_head list_node;

> >  } kdbtab_t;

> >

> >  extern int kdb_bt(int, const char **);       /* KDB display back trace */

> > --

> > 2.7.4
Daniel Thompson Jan. 19, 2021, 10:33 a.m. UTC | #3
On Tue, Jan 19, 2021 at 03:52:21PM +0530, Sumit Garg wrote:
> On Tue, 19 Jan 2021 at 15:20, Daniel Thompson

> <daniel.thompson@linaro.org> wrote:

> >

> > On Mon, Jan 18, 2021 at 06:30:13PM +0530, Sumit Garg wrote:

> > > Simplify kdb commands registration via using linked list instead of

> > > static array for commands storage.

> > >

> > > Signed-off-by: Sumit Garg <sumit.garg@linaro.org>

> > > ---

> > >

> > > Hi Daniel,

> > >

> > > This is my intial step towards kdb code refactoring. Please do let me

> > > know if I am headed in the right direction.

> >

> > I take it you're reflecting on the "you did start with the most

> > difficult kdb change to land" comments?

> 

> Yeah you took it right.

> 

> >

> > In that sense, yes. This is along the lines of what I originally

> > briefed. Basically try to reduce the w.t.f. per minute when reading

> > sources (and kdb scores highly on that measure).

> >

> 

> Sure, I will continue with this effort.

> 

> BTW, would you prefer me to push these code refactoring changes

> upstream as they are ready or prefer to prepare a patch-set and then

> post upstream collectively?


As they are ready seems best to me.


Daniel.
diff mbox series

Patch

diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c
index 930ac1b..93ac0f5 100644
--- a/kernel/debug/kdb/kdb_main.c
+++ b/kernel/debug/kdb/kdb_main.c
@@ -33,6 +33,7 @@ 
 #include <linux/kallsyms.h>
 #include <linux/kgdb.h>
 #include <linux/kdb.h>
+#include <linux/list.h>
 #include <linux/notifier.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
@@ -84,15 +85,8 @@  static unsigned int kdb_continue_catastrophic =
 static unsigned int kdb_continue_catastrophic;
 #endif
 
-/* kdb_commands describes the available commands. */
-static kdbtab_t *kdb_commands;
-#define KDB_BASE_CMD_MAX 50
-static int kdb_max_commands = KDB_BASE_CMD_MAX;
-static kdbtab_t kdb_base_commands[KDB_BASE_CMD_MAX];
-#define for_each_kdbcmd(cmd, num)					\
-	for ((cmd) = kdb_base_commands, (num) = 0;			\
-	     num < kdb_max_commands;					\
-	     num++, num == KDB_BASE_CMD_MAX ? cmd = kdb_commands : cmd++)
+/* kdb_cmds_head describes the available commands. */
+static LIST_HEAD(kdb_cmds_head);
 
 typedef struct _kdbmsg {
 	int	km_diag;	/* kdb diagnostic */
@@ -921,7 +915,7 @@  int kdb_parse(const char *cmdstr)
 	char *cp;
 	char *cpp, quoted;
 	kdbtab_t *tp;
-	int i, escaped, ignore_errors = 0, check_grep = 0;
+	int escaped, ignore_errors = 0, check_grep = 0;
 
 	/*
 	 * First tokenize the command string.
@@ -1011,7 +1005,7 @@  int kdb_parse(const char *cmdstr)
 		++argv[0];
 	}
 
-	for_each_kdbcmd(tp, i) {
+	list_for_each_entry(tp, &kdb_cmds_head, list_node) {
 		if (tp->cmd_name) {
 			/*
 			 * If this command is allowed to be abbreviated,
@@ -1037,8 +1031,8 @@  int kdb_parse(const char *cmdstr)
 	 * few characters of this match any of the known commands.
 	 * e.g., md1c20 should match md.
 	 */
-	if (i == kdb_max_commands) {
-		for_each_kdbcmd(tp, i) {
+	if (list_entry_is_head(tp, &kdb_cmds_head, list_node)) {
+		list_for_each_entry(tp, &kdb_cmds_head, list_node) {
 			if (tp->cmd_name) {
 				if (strncmp(argv[0],
 					    tp->cmd_name,
@@ -1049,7 +1043,7 @@  int kdb_parse(const char *cmdstr)
 		}
 	}
 
-	if (i < kdb_max_commands) {
+	if (!list_entry_is_head(tp, &kdb_cmds_head, list_node)) {
 		int result;
 
 		if (!kdb_check_flags(tp->cmd_flags, kdb_cmd_enabled, argc <= 1))
@@ -2428,12 +2422,11 @@  static int kdb_kgdb(int argc, const char **argv)
 static int kdb_help(int argc, const char **argv)
 {
 	kdbtab_t *kt;
-	int i;
 
 	kdb_printf("%-15.15s %-20.20s %s\n", "Command", "Usage", "Description");
 	kdb_printf("-----------------------------"
 		   "-----------------------------\n");
-	for_each_kdbcmd(kt, i) {
+	list_for_each_entry(kt, &kdb_cmds_head, list_node) {
 		char *space = "";
 		if (KDB_FLAG(CMD_INTERRUPT))
 			return 0;
@@ -2667,13 +2660,9 @@  int kdb_register_flags(char *cmd,
 		       short minlen,
 		       kdb_cmdflags_t flags)
 {
-	int i;
 	kdbtab_t *kp;
 
-	/*
-	 *  Brute force method to determine duplicates
-	 */
-	for_each_kdbcmd(kp, i) {
+	list_for_each_entry(kp, &kdb_cmds_head, list_node) {
 		if (kp->cmd_name && (strcmp(kp->cmd_name, cmd) == 0)) {
 			kdb_printf("Duplicate kdb command registered: "
 				"%s, func %px help %s\n", cmd, func, help);
@@ -2681,35 +2670,10 @@  int kdb_register_flags(char *cmd,
 		}
 	}
 
-	/*
-	 * Insert command into first available location in table
-	 */
-	for_each_kdbcmd(kp, i) {
-		if (kp->cmd_name == NULL)
-			break;
-	}
-
-	if (i >= kdb_max_commands) {
-		kdbtab_t *new = kmalloc_array(kdb_max_commands -
-						KDB_BASE_CMD_MAX +
-						kdb_command_extend,
-					      sizeof(*new),
-					      GFP_KDB);
-		if (!new) {
-			kdb_printf("Could not allocate new kdb_command "
-				   "table\n");
-			return 1;
-		}
-		if (kdb_commands) {
-			memcpy(new, kdb_commands,
-			  (kdb_max_commands - KDB_BASE_CMD_MAX) * sizeof(*new));
-			kfree(kdb_commands);
-		}
-		memset(new + kdb_max_commands - KDB_BASE_CMD_MAX, 0,
-		       kdb_command_extend * sizeof(*new));
-		kdb_commands = new;
-		kp = kdb_commands + kdb_max_commands - KDB_BASE_CMD_MAX;
-		kdb_max_commands += kdb_command_extend;
+	kp = kmalloc(sizeof(*kp), GFP_KDB);
+	if (!kp) {
+		kdb_printf("Could not allocate new kdb_command table\n");
+		return 1;
 	}
 
 	kp->cmd_name   = cmd;
@@ -2719,6 +2683,8 @@  int kdb_register_flags(char *cmd,
 	kp->cmd_minlen = minlen;
 	kp->cmd_flags  = flags;
 
+	list_add_tail(&kp->list_node, &kdb_cmds_head);
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(kdb_register_flags);
@@ -2757,15 +2723,15 @@  EXPORT_SYMBOL_GPL(kdb_register);
  */
 int kdb_unregister(char *cmd)
 {
-	int i;
 	kdbtab_t *kp;
 
 	/*
 	 *  find the command.
 	 */
-	for_each_kdbcmd(kp, i) {
+	list_for_each_entry(kp, &kdb_cmds_head, list_node) {
 		if (kp->cmd_name && (strcmp(kp->cmd_name, cmd) == 0)) {
-			kp->cmd_name = NULL;
+			list_del(&kp->list_node);
+			kfree(kp);
 			return 0;
 		}
 	}
@@ -2778,12 +2744,6 @@  EXPORT_SYMBOL_GPL(kdb_unregister);
 /* Initialize the kdb command table. */
 static void __init kdb_inittab(void)
 {
-	int i;
-	kdbtab_t *kp;
-
-	for_each_kdbcmd(kp, i)
-		kp->cmd_name = NULL;
-
 	kdb_register_flags("md", kdb_md, "<vaddr>",
 	  "Display Memory Contents, also mdWcN, e.g. md8c1", 1,
 	  KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS);
diff --git a/kernel/debug/kdb/kdb_private.h b/kernel/debug/kdb/kdb_private.h
index a4281fb..7a4a181 100644
--- a/kernel/debug/kdb/kdb_private.h
+++ b/kernel/debug/kdb/kdb_private.h
@@ -174,6 +174,7 @@  typedef struct _kdbtab {
 	short    cmd_minlen;		/* Minimum legal # command
 					 * chars required */
 	kdb_cmdflags_t cmd_flags;	/* Command behaviour flags */
+	struct list_head list_node;
 } kdbtab_t;
 
 extern int kdb_bt(int, const char **);	/* KDB display back trace */