Re: [PATCH V2] mmc: core: cd_label must be last entry of mmc_gpio struct

From: Linus Walleij
Date: Mon Jul 02 2018 - 07:42:46 EST


On Mon, Jul 2, 2018 at 3:32 AM Anson Huang <Anson.Huang@xxxxxxx> wrote:

> commit bfd694d5e21c ("mmc: core: Add tunable delay
> before detecting card after card is inserted") adds
> "u32 cd_debounce_delay_ms" to the last of mmc_gpio
> struct and cause "char cd_label[0]" NOT work as string
> pointer of card detect label, when "cat /proc/interrupts",
> the devname for card detect gpio is incorrect as below:
>
> 144: 0 gpio-mxc 22 Edge â
> 161: 0 gpio-mxc 7 Edge â
>
> Move the cd_label field down to fix this, and drop the
> zero from the array size to prevent future similar bugs,
> the result is correct as below:
>
> 144: 0 gpio-mxc 22 Edge 2198000.mmc cd
> 161: 0 gpio-mxc 7 Edge 2190000.mmc cd
>
> Fixes: bfd694d5e21c ("mmc: core: Add tunable delay before detecting card after card is inserted")
> Signed-off-by: Anson Huang <Anson.Huang@xxxxxxx>
> Tested-by: Fabio Estevam <fabio.estevam@xxxxxxx>

Curious.

> --- a/drivers/mmc/core/slot-gpio.c
> +++ b/drivers/mmc/core/slot-gpio.c
> @@ -27,8 +27,8 @@ struct mmc_gpio {
> bool override_cd_active_level;
> irqreturn_t (*cd_gpio_isr)(int irq, void *dev_id);
> char *ro_label;
> - char cd_label[0];
> u32 cd_debounce_delay_ms;
> + char cd_label[];

Not that I am the smartest in the world when it comes to how the
C compilers work this out.

But isn't that equivalent to:
char *cd_label;
?

Look at this from drivers/mmc/core/slot-gpio.c:

ctx->ro_label = ctx->cd_label + len;
ctx->cd_debounce_delay_ms = 200;
snprintf(ctx->cd_label, len, "%s cd", dev_name(host->parent));
snprintf(ctx->ro_label, len, "%s ro", dev_name(host->parent));
host->slot.handler_priv = ctx;
host->slot.cd_irq = -EINVAL;

So now that ro_label is char * that points len chars into the
struct and that is all fine as the ctx is allocated like that:

struct mmc_gpio *ctx = devm_kzalloc(host->parent,
sizeof(*ctx) + 2 * len, GFP_KERNEL);

And I've seen this being done to allocate a state with
some dynamic strings after it.

But I just don't like this, it seems fragile and now it broke.

What about this: