Received: by 10.213.65.68 with SMTP id h4csp102237imn; Tue, 27 Mar 2018 17:38:32 -0700 (PDT) X-Google-Smtp-Source: AIpwx48erkLrS2FMDI8nO3OP0UhtV0kp/LaSw6AOlIn3KqVi5vzOoTskzR2W/hAmMJ/RTJ84ANQ8 X-Received: by 2002:a17:902:744b:: with SMTP id e11-v6mr1441681plt.351.1522197512453; Tue, 27 Mar 2018 17:38:32 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1522197512; cv=none; d=google.com; s=arc-20160816; b=X+2TsQz7RkJ7R8m9lRGzb/nd/9p7IDr1NhSk9D7ayk0/oA+J39VOTTtQEQUVE7Rfl9 6a0FbcrmoOI5L7yZqhewxgnzXHVNBR+xN8FAvx67/PuzKHWK8zUJ6HVgl8qysmt9V6gy jycWkcRWtpO18BnMGCngneZ9jC86MmRQcw3DKRrbiGgSiygmZ7O3vI6D1yl3u01tUR5P IrjMyUvnmf+SlSXCKCAp1SrJeq2upAiFcAF7tEkw98hiMSm/31YXanjR4FjkjMmeVmg+ 1aRKPJFMEfKtjPSpGWAUhAIptSZ01kutNWE1RQWnHJoD9ZxG9aTNGIjSPiiP9FlHvdIg iSVg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding :content-language:in-reply-to:mime-version:user-agent:date :message-id:from:references:cc:to:subject:arc-authentication-results; bh=luWMVxkIU2JC13STYk6FCwlxHiEtK91jRhznNFQWJpM=; b=nDpJLL8aXpJ4kEfEP3rghz8eMhCX4k91KcgzL1D4Qd/tWFGi8XIj3RCDOK2c9MAEB1 n1ST9iIDVsDPZa/HxPn+yAFjVh5/0mPN836l15m4N+ewpmiJU+83H5pDU168/heeZeeT rYSAk275dVk8CWGRK9GunDUpoeuAL4K06xYfKW0EvHegpFumJ3JAkt0RAfuKKePblhgo DrUZWS1amV6L6AZbi5AEgQH4tSUNiWgEjkLOKWFPgxGKIoE+HgFNXmX3eGX4rzTo+7MT +ez7kKjWV2ZLRXeoMjDI1jiGmNGFBrDuW8SwL0bsrEnpgFSXk/KrLCUPGCUo7A0qSp0T 8vYg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=redhat.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id a63-v6si2308675pla.718.2018.03.27.17.38.17; Tue, 27 Mar 2018 17:38:32 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752547AbeC1AhY (ORCPT + 99 others); Tue, 27 Mar 2018 20:37:24 -0400 Received: from mail-ot0-f194.google.com ([74.125.82.194]:38111 "EHLO mail-ot0-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752279AbeC1AhW (ORCPT ); Tue, 27 Mar 2018 20:37:22 -0400 Received: by mail-ot0-f194.google.com with SMTP id o9-v6so820640otj.5 for ; Tue, 27 Mar 2018 17:37:22 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:to:cc:references:from:message-id:date :user-agent:mime-version:in-reply-to:content-language :content-transfer-encoding; bh=luWMVxkIU2JC13STYk6FCwlxHiEtK91jRhznNFQWJpM=; b=iUr2gCv3kDvPHHHddvD39od0UpZY/Ll/rwBAnMP6NO5h03selUmUXvdf+cr6nlpweq 8tr+OErbnnSSeHRJSMJJcCkQGC7G75L9UUoT3Tpiw9ujgS2xg8HhQRDGRPcwaaoGH4+f +40jsyB/rWmcmT4LiyoDvzbcMxk7lkJy9trr3Q8i5m2wJ11YMj8gC9BXp4dpTyrHOHBa 1831/UnCagqlOCOTr+gMc4+VIHPFTF9k21OoFGqwtQD2f4ADS8x1NtT/Wt0571qtc/+f jt9B557E+sb6dherVXgZsjmUtO2lLkgQLMNtMUm1wgJ8uYSYfUPk1WM4/CMFHstOd2BW 1i8Q== X-Gm-Message-State: AElRT7HmhivzDd8Ri/vcc8SIq26Is0XjBUGMBoEzi4m3XQ5orN7KUHQA RTFUjtt9xnzTOZJ4XquiidkmUA== X-Received: by 2002:a9d:5a14:: with SMTP id v20-v6mr991473oth.349.1522197441646; Tue, 27 Mar 2018 17:37:21 -0700 (PDT) Received: from ?IPv6:2601:602:9802:a8dc:4eb2:6dae:ab32:e5b0? ([2601:602:9802:a8dc:4eb2:6dae:ab32:e5b0]) by smtp.gmail.com with ESMTPSA id g192-v6sm1397701oic.50.2018.03.27.17.37.19 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 27 Mar 2018 17:37:20 -0700 (PDT) Subject: Re: [PATCH 1/4] gpio: Remove VLA from gpiolib To: Lukas Wunner , Rasmus Villemoes Cc: Linus Walleij , Kees Cook , linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, kernel-hardening@lists.openwall.com, Mathias Duckeck , Nandor Han , Semi Malinen , Patrice Chotard References: <20180310001021.6437-1-labbott@redhat.com> <20180310001021.6437-2-labbott@redhat.com> <20180317082509.GA2579@wunner.de> <20180318142327.GA23761@wunner.de> From: Laura Abbott Message-ID: Date: Tue, 27 Mar 2018 17:37:18 -0700 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.6.0 MIME-Version: 1.0 In-Reply-To: <20180318142327.GA23761@wunner.de> Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 03/18/2018 07:23 AM, Lukas Wunner wrote: > On Sat, Mar 17, 2018 at 09:25:09AM +0100, Lukas Wunner wrote: >> On Mon, Mar 12, 2018 at 04:00:36PM +0100, Rasmus Villemoes wrote: >>> On 2018-03-10 01:10, Laura Abbott wrote: >>>> @@ -2887,14 +2909,30 @@ void gpiod_set_array_value_complex(bool raw, bool can_sleep, >>>> >>>> while (i < array_size) { >>>> struct gpio_chip *chip = desc_array[i]->gdev->chip; >>>> - unsigned long mask[BITS_TO_LONGS(chip->ngpio)]; >>>> - unsigned long bits[BITS_TO_LONGS(chip->ngpio)]; >>>> + unsigned long *mask; >>>> + unsigned long *bits; >>>> int count = 0; >>>> >>>> + mask = kmalloc_array(BITS_TO_LONGS(chip->ngpio), >>>> + sizeof(*mask), >>>> + can_sleep ? GFP_KERNEL : GFP_ATOMIC); >>>> + >>>> + if (!mask) >>>> + return; >>>> + >>>> + bits = kmalloc_array(BITS_TO_LONGS(chip->ngpio), >>>> + sizeof(*bits), >>>> + can_sleep ? GFP_KERNEL : GFP_ATOMIC); >>>> + >>>> + if (!bits) { >>>> + kfree(mask); >>>> + return; >>>> + } >>>> + >>>> if (!can_sleep) >>>> WARN_ON(chip->can_sleep); >>>> >>>> - memset(mask, 0, sizeof(mask)); >>>> + memset(mask, 0, sizeof(*mask)); >>> >>> Other random thoughts: maybe two allocations for each loop iteration is >>> a bit much. Maybe do a first pass over the array and collect the maximal >>> chip->ngpio, do the memory allocation and freeing outside the loop (then >>> you'd of course need to preserve the memset() with appropriate length >>> computed). And maybe even just do one allocation, making bits point at >>> the second half. >> >> I think those are great ideas because the function is kind of a hotpath >> and usage of VLAs was motivated by the desire to make it fast. >> >> I'd go one step further and store the maximum ngpio of all registered >> chips in a global variable (and update it in gpiochip_add_data_with_key()), >> then allocate 2 * max_ngpio once before entering the loop (as you've >> suggested). That would avoid the first pass to determine the maximum >> chip->ngpio. In most systems max_ngpio will be < 64, so one or two >> unsigned longs depending on the arch's bitness. > > Actually, scratch that. If ngpio is usually smallish, we can just > allocate reasonably sized space for mask and bits on the stack, > and fall back to the kcalloc slowpath only if chip->ngpio exceeds > that limit. Basically the below (likewise compile-tested only), > this is on top of Laura's patch, could be squashed together. > Let me know what you think, thanks. > It seems like there's general consensus this is okay so I'm going to fold it into the next version. If not, we can discuss again. > -- >8 -- > Subject: [PATCH] gpio: Add fastpath to gpiod_get/set_array_value_complex() > > Signed-off-by: Lukas Wunner > --- > drivers/gpio/gpiolib.c | 76 ++++++++++++++++++++++++-------------------------- > 1 file changed, 37 insertions(+), 39 deletions(-) > > diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c > index 429bc251392b..ffc67b0b866c 100644 > --- a/drivers/gpio/gpiolib.c > +++ b/drivers/gpio/gpiolib.c > @@ -2432,6 +2432,8 @@ static int gpio_chip_get_multiple(struct gpio_chip *chip, > return -EIO; > } > > +#define FASTPATH_NGPIO 256 > + > int gpiod_get_array_value_complex(bool raw, bool can_sleep, > unsigned int array_size, > struct gpio_desc **desc_array, > @@ -2441,27 +2443,24 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep, > > while (i < array_size) { > struct gpio_chip *chip = desc_array[i]->gdev->chip; > - unsigned long *mask; > - unsigned long *bits; > + unsigned long fastpath[2 * BITS_TO_LONGS(FASTPATH_NGPIO)]; > + unsigned long *slowpath = NULL, *mask, *bits; > int first, j, ret; > > - mask = kcalloc(BITS_TO_LONGS(chip->ngpio), > - sizeof(*mask), > - can_sleep ? GFP_KERNEL : GFP_ATOMIC); > - > - if (!mask) > - return -ENOMEM; > - > - bits = kcalloc(BITS_TO_LONGS(chip->ngpio), > - sizeof(*bits), > - can_sleep ? GFP_KERNEL : GFP_ATOMIC); > - > - if (!bits) { > - kfree(mask); > - return -ENOMEM; > + if (likely(chip->ngpio <= FASTPATH_NGPIO)) { > + memset(fastpath, 0, sizeof(fastpath)); > + mask = fastpath; > + bits = fastpath + BITS_TO_LONGS(FASTPATH_NGPIO); > + } else { > + slowpath = kcalloc(2 * BITS_TO_LONGS(chip->ngpio), > + sizeof(*slowpath), > + can_sleep ? GFP_KERNEL : GFP_ATOMIC); > + if (!slowpath) > + return -ENOMEM; > + mask = slowpath; > + bits = slowpath + BITS_TO_LONGS(chip->ngpio); > } > > - > if (!can_sleep) > WARN_ON(chip->can_sleep); > > @@ -2478,8 +2477,8 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep, > > ret = gpio_chip_get_multiple(chip, mask, bits); > if (ret) { > - kfree(bits); > - kfree(mask); > + if (slowpath) > + kfree(slowpath); > return ret; > } > > @@ -2493,8 +2492,9 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep, > value_array[j] = value; > trace_gpio_value(desc_to_gpio(desc), 1, value); > } > - kfree(bits); > - kfree(mask); > + > + if (slowpath) > + kfree(slowpath); > } > return 0; > } > @@ -2699,24 +2699,22 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep, > > while (i < array_size) { > struct gpio_chip *chip = desc_array[i]->gdev->chip; > - unsigned long *mask; > - unsigned long *bits; > + unsigned long fastpath[2 * BITS_TO_LONGS(FASTPATH_NGPIO)]; > + unsigned long *slowpath = NULL, *mask, *bits; > int count = 0; > > - mask = kcalloc(BITS_TO_LONGS(chip->ngpio), > - sizeof(*mask), > - can_sleep ? GFP_KERNEL : GFP_ATOMIC); > - > - if (!mask) > - return -ENOMEM; > - > - bits = kcalloc(BITS_TO_LONGS(chip->ngpio), > - sizeof(*bits), > - can_sleep ? GFP_KERNEL : GFP_ATOMIC); > - > - if (!bits) { > - kfree(mask); > - return -ENOMEM; > + if (likely(chip->ngpio <= FASTPATH_NGPIO)) { > + memset(fastpath, 0, sizeof(fastpath)); > + mask = fastpath; > + bits = fastpath + BITS_TO_LONGS(FASTPATH_NGPIO); > + } else { > + slowpath = kcalloc(2 * BITS_TO_LONGS(chip->ngpio), > + sizeof(*slowpath), > + can_sleep ? GFP_KERNEL : GFP_ATOMIC); > + if (!slowpath) > + return -ENOMEM; > + mask = slowpath; > + bits = slowpath + BITS_TO_LONGS(chip->ngpio); > } > > if (!can_sleep) > @@ -2753,8 +2751,8 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep, > if (count != 0) > gpio_chip_set_multiple(chip, mask, bits); > > - kfree(mask); > - kfree(bits); > + if (slowpath) > + kfree(slowpath); > } > return 0; > } >