All of lore.kernel.org
 help / color / mirror / Atom feed
From: Dan Carpenter <dan.carpenter@oracle.com>
To: Julia Lawall <Julia.Lawall@lip6.fr>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	devel@driverdev.osuosl.org, "Dilger,
	Andreas" <andreas.dilger@intel.com>,
	Peng Tao <bergwolf@gmail.com>,
	kernel-janitors@vger.kernel.org, linux-kernel@vger.kernel.org,
	"Drokin, Oleg" <oleg.drokin@intel.com>
Subject: Re: [PATCH 6/7] staging: lustre: obdclass: expand the GOTO macro + break
Date: Tue, 9 Sep 2014 15:54:10 +0300	[thread overview]
Message-ID: <20140909125410.GJ6549@mwanda> (raw)
In-Reply-To: <1410106715-9573-6-git-send-email-Julia.Lawall@lip6.fr>

On Sun, Sep 07, 2014 at 06:18:34PM +0200, Julia Lawall wrote:
> diff --git a/drivers/staging/lustre/lustre/obdclass/obd_config.c b/drivers/staging/lustre/lustre/obdclass/obd_config.c
> index f41695d..8a9752f 100644
> --- a/drivers/staging/lustre/lustre/obdclass/obd_config.c
> +++ b/drivers/staging/lustre/lustre/obdclass/obd_config.c
> @@ -1226,25 +1226,25 @@ int class_process_config(struct lustre_cfg *lcfg)
>  	}
>  	case LCFG_POOL_NEW: {
>  		err = obd_pool_new(obd, lustre_cfg_string(lcfg, 2));
> -		GOTO(out, err = 0);
> -		break;
> +		err = 0;
> +		goto out;

[ Warning:  this email is long and not related to your code.  It's just
  the frustrations of dealing with lustre.  ]

So now the code reads:

		err = obd_pool_new(obd, lustre_cfg_string(lcfg, 2));
		err = 0;

That was there in the original code, and your patch is correct to leave
the suspicous looking code as is.  We used to have a GCC warning for
this but the linux kernel source has too much bad code so we had to
disable the warning.

I wonder what happens if obd_pool_new() fails?  Unfortunately "make
cscope" and "vim -t obd_pool_new" doesn't work with lustre so you have
to grep for it.

grep obd_pool_new drivers/staging/lustre/ -R |egrep '\.[ch]:'

This is the only caller so we can't compare with the other callers to
see if they check the return value.

Here is how the obd_pool_new() function is implemented.

  1051  static inline int obd_pool_new(struct obd_device *obd, char *poolname)
  1052  {
  1053          int rc;
  1054  
  1055          OBD_CHECK_DT_OP(obd, pool_new, -EOPNOTSUPP);
  1056          OBD_COUNTER_INCREMENT(obd, pool_new);
  1057  
  1058          rc = OBP(obd, pool_new)(obd, poolname);
  1059          return rc;
  1060  }

This whole function is just macros.  Let's see what they do:

   460  #define OBD_CHECK_DT_OP(obd, op, err)                      \
   461  do {                                                        \
   462          if (!OBT(obd) || !OBP((obd), op)) {                  \
   463                  if (err)                                        \
   464                          CERROR("obd_" #op ": dev %d no operation\n",    \
   465                                 obd->obd_minor);          \
   466                  return err;                                 \
   467          }                                                      \
   468  } while (0)

Wow!  What a terrible macro!  None of the '\' are in a line.  There is
a hidden return statement in it which is a terrible thing and flow
control statements are not allowed inside macros.

I can't tell what OBT() and OBP() because the names are very ambiguous.

   328  #define OBT(dev)        (dev)->obd_type
   329  #define OBP(dev, op)    (dev)->obd_type->typ_dt_ops->o_ ## op
   330  #define MDP(dev, op)    (dev)->obd_type->typ_md_ops->m_ ## op

Ok.  "OB" stands for "obd".  T stands for "type".  The "P" probably
stands for pointer or operation.  MD is clear enough.

The OBP() macro adds an "o_" to the function pointer and the MDP() macro
adds an "m_".  That totally sucks because it makes the function pointer
hard to grep for.  There isn't another explanation, whoever wrote this
code is just being ornery.

Summary so far:  OBD_CHECK_DT_OP() checks to see if a function pointer
is NULL.

Let's see what OBD_COUNTER_INCREMENT() does.

   361  #define OBD_COUNTER_INCREMENT(obdx, op)                    \
   362          if ((obdx)->obd_stats != NULL) {                          \
   363                  unsigned int coffset;                        \
   364                  coffset = (unsigned int)((obdx)->obd_cntr_base) + \
   365                          OBD_COUNTER_OFFSET(op);            \
   366                  LASSERT(coffset < (obdx)->obd_stats->ls_num);     \
   367                  lprocfs_counter_incr((obdx)->obd_stats, coffset); \
   368          }
   369  

That's a densely packed block of messy code but it basically does what
you'd expect from the name.  Fair enough.

So the obd_pool_new() function verifies that ->o_pool_new is non-NULL,
it increments a counter and calls ->o_pool_new().  Let's take a look at
which functions implement ->o_pool_new().

grep -w o_pool_new drivers/staging/lustre/ -R | egrep '\.[ch]:'

The only implementation of this function is lov_pool_new().  Why do
we have a function pointer if there is only one implementation?  We
should remove this.

The lov_pool_new() function definitely can fail unexpectedly with
-ENOMEM.

Let's go back to the original code and see how the error should be
handled...  Oh...  Apparently this is an optional thing so we would
just ignore the error and continue.  The code is fine.

In any other subsystem it would have taken 30 seconds to read the code
because cscope would work and there wouldn't be the layers of
indirection.

I'm not convinced that having a function counter for calls to
lov_pool_new() is useful.  We could get the same information from ftrace
or other tools.  In my view, we could get rid of all the horrible macros
and the function pointers and the splitting names into half and the
layers of indirection and the debugging code and just call
lov_pool_new() directly.

regards,
dan carpenter


WARNING: multiple messages have this Message-ID (diff)
From: Dan Carpenter <dan.carpenter@oracle.com>
To: Julia Lawall <Julia.Lawall@lip6.fr>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	devel@driverdev.osuosl.org, "Dilger,
	Andreas" <andreas.dilger@intel.com>,
	Peng Tao <bergwolf@gmail.com>,
	kernel-janitors@vger.kernel.org, linux-kernel@vger.kernel.org,
	"Drokin, Oleg" <oleg.drokin@intel.com>
Subject: Re: [PATCH 6/7] staging: lustre: obdclass: expand the GOTO macro + break
Date: Tue, 09 Sep 2014 12:54:10 +0000	[thread overview]
Message-ID: <20140909125410.GJ6549@mwanda> (raw)
In-Reply-To: <1410106715-9573-6-git-send-email-Julia.Lawall@lip6.fr>

On Sun, Sep 07, 2014 at 06:18:34PM +0200, Julia Lawall wrote:
> diff --git a/drivers/staging/lustre/lustre/obdclass/obd_config.c b/drivers/staging/lustre/lustre/obdclass/obd_config.c
> index f41695d..8a9752f 100644
> --- a/drivers/staging/lustre/lustre/obdclass/obd_config.c
> +++ b/drivers/staging/lustre/lustre/obdclass/obd_config.c
> @@ -1226,25 +1226,25 @@ int class_process_config(struct lustre_cfg *lcfg)
>  	}
>  	case LCFG_POOL_NEW: {
>  		err = obd_pool_new(obd, lustre_cfg_string(lcfg, 2));
> -		GOTO(out, err = 0);
> -		break;
> +		err = 0;
> +		goto out;

[ Warning:  this email is long and not related to your code.  It's just
  the frustrations of dealing with lustre.  ]

So now the code reads:

		err = obd_pool_new(obd, lustre_cfg_string(lcfg, 2));
		err = 0;

That was there in the original code, and your patch is correct to leave
the suspicous looking code as is.  We used to have a GCC warning for
this but the linux kernel source has too much bad code so we had to
disable the warning.

I wonder what happens if obd_pool_new() fails?  Unfortunately "make
cscope" and "vim -t obd_pool_new" doesn't work with lustre so you have
to grep for it.

grep obd_pool_new drivers/staging/lustre/ -R |egrep '\.[ch]:'

This is the only caller so we can't compare with the other callers to
see if they check the return value.

Here is how the obd_pool_new() function is implemented.

  1051  static inline int obd_pool_new(struct obd_device *obd, char *poolname)
  1052  {
  1053          int rc;
  1054  
  1055          OBD_CHECK_DT_OP(obd, pool_new, -EOPNOTSUPP);
  1056          OBD_COUNTER_INCREMENT(obd, pool_new);
  1057  
  1058          rc = OBP(obd, pool_new)(obd, poolname);
  1059          return rc;
  1060  }

This whole function is just macros.  Let's see what they do:

   460  #define OBD_CHECK_DT_OP(obd, op, err)                      \
   461  do {                                                        \
   462          if (!OBT(obd) || !OBP((obd), op)) {                  \
   463                  if (err)                                        \
   464                          CERROR("obd_" #op ": dev %d no operation\n",    \
   465                                 obd->obd_minor);          \
   466                  return err;                                 \
   467          }                                                      \
   468  } while (0)

Wow!  What a terrible macro!  None of the '\' are in a line.  There is
a hidden return statement in it which is a terrible thing and flow
control statements are not allowed inside macros.

I can't tell what OBT() and OBP() because the names are very ambiguous.

   328  #define OBT(dev)        (dev)->obd_type
   329  #define OBP(dev, op)    (dev)->obd_type->typ_dt_ops->o_ ## op
   330  #define MDP(dev, op)    (dev)->obd_type->typ_md_ops->m_ ## op

Ok.  "OB" stands for "obd".  T stands for "type".  The "P" probably
stands for pointer or operation.  MD is clear enough.

The OBP() macro adds an "o_" to the function pointer and the MDP() macro
adds an "m_".  That totally sucks because it makes the function pointer
hard to grep for.  There isn't another explanation, whoever wrote this
code is just being ornery.

Summary so far:  OBD_CHECK_DT_OP() checks to see if a function pointer
is NULL.

Let's see what OBD_COUNTER_INCREMENT() does.

   361  #define OBD_COUNTER_INCREMENT(obdx, op)                    \
   362          if ((obdx)->obd_stats != NULL) {                          \
   363                  unsigned int coffset;                        \
   364                  coffset = (unsigned int)((obdx)->obd_cntr_base) + \
   365                          OBD_COUNTER_OFFSET(op);            \
   366                  LASSERT(coffset < (obdx)->obd_stats->ls_num);     \
   367                  lprocfs_counter_incr((obdx)->obd_stats, coffset); \
   368          }
   369  

That's a densely packed block of messy code but it basically does what
you'd expect from the name.  Fair enough.

So the obd_pool_new() function verifies that ->o_pool_new is non-NULL,
it increments a counter and calls ->o_pool_new().  Let's take a look at
which functions implement ->o_pool_new().

grep -w o_pool_new drivers/staging/lustre/ -R | egrep '\.[ch]:'

The only implementation of this function is lov_pool_new().  Why do
we have a function pointer if there is only one implementation?  We
should remove this.

The lov_pool_new() function definitely can fail unexpectedly with
-ENOMEM.

Let's go back to the original code and see how the error should be
handled...  Oh...  Apparently this is an optional thing so we would
just ignore the error and continue.  The code is fine.

In any other subsystem it would have taken 30 seconds to read the code
because cscope would work and there wouldn't be the layers of
indirection.

I'm not convinced that having a function counter for calls to
lov_pool_new() is useful.  We could get the same information from ftrace
or other tools.  In my view, we could get rid of all the horrible macros
and the function pointers and the splitting names into half and the
layers of indirection and the debugging code and just call
lov_pool_new() directly.

regards,
dan carpenter


  reply	other threads:[~2014-09-09 12:54 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-09-07 16:18 [PATCH 6/7] staging: lustre: obdclass: expand the GOTO macro + break Julia Lawall
2014-09-07 16:18 ` Julia Lawall
2014-09-09 12:54 ` Dan Carpenter [this message]
2014-09-09 12:54   ` Dan Carpenter
2014-09-09 13:05   ` Julia Lawall
2014-09-09 13:05     ` Julia Lawall
2014-09-09 13:37   ` Drokin, Oleg
2014-09-09 13:37     ` Drokin, Oleg
2014-09-09 20:38   ` [PATCH] checkpatch: Warn on macros with flow control statements Joe Perches
2014-09-09 20:38     ` Joe Perches
2014-09-10  8:43     ` Dan Carpenter
2014-09-10  8:43       ` Dan Carpenter
2014-09-10 13:55       ` Joe Perches
2014-09-10 13:55         ` Joe Perches
2014-09-10 14:06         ` Julia Lawall
2014-09-10 14:06           ` Julia Lawall
2014-09-10 14:36           ` Joe Perches
2014-09-10 14:36             ` Joe Perches
2014-09-10 14:52             ` Drokin, Oleg

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=20140909125410.GJ6549@mwanda \
    --to=dan.carpenter@oracle.com \
    --cc=Julia.Lawall@lip6.fr \
    --cc=andreas.dilger@intel.com \
    --cc=bergwolf@gmail.com \
    --cc=devel@driverdev.osuosl.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=kernel-janitors@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=oleg.drokin@intel.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.