From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-ot0-f193.google.com (mail-ot0-f193.google.com [74.125.82.193]) by dpdk.org (Postfix) with ESMTP id 6C02BF04 for ; Tue, 26 Jun 2018 03:09:41 +0200 (CEST) Received: by mail-ot0-f193.google.com with SMTP id i19-v6so17188389otk.10 for ; Mon, 25 Jun 2018 18:09:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=XW2lnBF8on6fAvWx9r8l1h2RYvwSR3AMUafhScxZUSk=; b=swEkUpGZmY3AAgIIjU/lOKJAfY3q8yjzCgHFoNayu0h/WfGjZtiADU91Fw/rpXU9oI KOmIu52psyIkub/kgxVuYN03/UdU1nGnxf8fkTcqkGbG8IikJxYTC2tx2nbB8VgHnxFP 1aA/es9XbgCOaGYWEfIsVtpzGrdRJK4m4yhgcCn8kxjUO6ZcxrMoXQ+S41yqFGROQj7W sapuOOKHqXrpQnq5bQ3/S6jgbmjkFmCQZBXReHT1fun2IAb5WZa/m9PPx3gyW1mPZyh/ LUoutz16nnL1hHqX5QNa4kV6LYhF3+qXupVggG+v+NMc6KC4NaOi2o7c7DA5UyD/zJdr LPwg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=XW2lnBF8on6fAvWx9r8l1h2RYvwSR3AMUafhScxZUSk=; b=In23V24En6gzhIiDCPT86rAYeBug96PMJv+Uv51tGmG0sHVW0+nuhiX/n73GySlEPe e1EtPG61iP/kAbmbolcKfLtSz8LbFhthuR3rIp9aac0ljy2Nld+RtDvzY1VdWNCb2COI xxbNUyMrufzmAegd6y0xdrdDKnexqPQC0FQkADYTJGgYxc6AybuqrKYSEQyIhMPHy5+x q6Y7aqTU5TmT9jI/p3s04zqKWt0+8CghnENCYuzJ3aHq4xlF8I62m8V3spATt6jrgACn /mZA/VAZ4pnt0AT/2kJFcXieQEe0cWKwOozOhxZxlzyFyzejSY1hhXEzHSrThmpB6axH YRcA== X-Gm-Message-State: APt69E3cdkMBLOHMInLkB+x6G4JPN2o5pWfVeBHIkBq7eMI4H2DUZNvq MqBsckiWIEWJreolRcKXgLkevkjOZ6xEqGHNgCU= X-Google-Smtp-Source: AAOMgpeB+7Yk1fO/i9ObPpzmWTDybFV8AzAX0V2tyjJJEJ4Xm302E4qPjBc/d+nBeqz432GhUT1f/BHnwxzZ9DATDPw= X-Received: by 2002:a9d:1370:: with SMTP id q45-v6mr1629200otq.46.1529975379307; Mon, 25 Jun 2018 18:09:39 -0700 (PDT) MIME-Version: 1.0 Received: by 2002:a4a:8f42:0:0:0:0:0 with HTTP; Mon, 25 Jun 2018 18:09:38 -0700 (PDT) In-Reply-To: <02efa4a4e6fab105ae883a855ae1985afc208a31.1529940601.git.anatoly.burakov@intel.com> References: <02efa4a4e6fab105ae883a855ae1985afc208a31.1529940601.git.anatoly.burakov@intel.com> From: Kevin Wilson Date: Tue, 26 Jun 2018 04:09:38 +0300 Message-ID: To: Anatoly Burakov Cc: dev@dpdk.org, john.mcnamara@intel.com, bruce.richardson@intel.com, pablo.de.lara.guarch@intel.com, david.hunt@intel.com, mohammad.abdul.awal@intel.com Content-Type: text/plain; charset="UTF-8" Subject: Re: [dpdk-dev] [RFC 9/9] usertools/lib: add GRUB utility library for hugepage config X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 26 Jun 2018 01:09:41 -0000 Hi, Anatoly, Thanks for these patches, good work. Regarding "update-grub": IIRC, this is Ubuntu specific command (and also used in Debian/Debian based flavors). In Fedora (RedHat based) recent distros, you use grub2-mkconfig instead (and there is no "update-grub", IIRC). If this is true, I would consider adding a comment in the commit log saying something like "it is for Ubuntu/Debian-based distros". So maybe in the future someone will add the python code which detects the OS (using lsb-release, etc) and, in case it is Fedora/RedHat distro, the grub2-mkconfig util will be invoked instead. Regards, KW On Mon, Jun 25, 2018 at 6:59 PM, Anatoly Burakov wrote: > This library is highly experimental and can kill kittens, but its > main purpose is to automatically set up GRUB command-line to > allocate a given number of hugepages at boot time. It works in > a similar way HugeUtil library does, but instead of committing > changes to fstab or runtime configuration, it commits its > changes to GRUB default command-line and updates all GRUB entries > afterwards. I got it to a state where it's safe to use on my > system, but see the part above about killing kittens - you have > been warned :) > > No example scripts will currently be provided. > > Signed-off-by: Anatoly Burakov > --- > usertools/DPDKConfigLib/GrubHugeUtil.py | 175 ++++++++++++++++++++++++ > 1 file changed, 175 insertions(+) > create mode 100755 usertools/DPDKConfigLib/GrubHugeUtil.py > > diff --git a/usertools/DPDKConfigLib/GrubHugeUtil.py b/usertools/DPDKConfigLib/GrubHugeUtil.py > new file mode 100755 > index 000000000..4b8e349b8 > --- /dev/null > +++ b/usertools/DPDKConfigLib/GrubHugeUtil.py > @@ -0,0 +1,175 @@ > +#!/usr/bin/env python > +# SPDX-License-Identifier: BSD-3-Clause > +# Copyright(c) 2018 Intel Corporation > + > + > +from .PlatformInfo import * > +from .Util import * > +import re > +import os > + > +__KERNEL_TRANSPARENT_HP = "/sys/kernel/mm/transparent_hugepage/enabled" > +_GRUB_CMDLINE_PARAM_NAME = "GRUB_CMDLINE_LINUX_DEFAULT" > + > +# local copy of platform info > +info = PlatformInfo() > + > +def _find_linux_default_cmdline(): > + with open("/etc/default/grub") as f: > + for line in f: > + line = line.strip() > + if line.startswith(_GRUB_CMDLINE_PARAM_NAME): > + return line > + else: > + raise RuntimeError("Invalid GRUB default configuration format") > + > + > +def _parse_linux_default_cmdline(line): > + # get value to the right of equals sign, strip whitespace and quotes, > + # split into separate keys and make a list of values > + _, cmdline = kv_split(line, "=") > + # remove quotes > + if cmdline[0] == cmdline[-1] == '"': > + cmdline = cmdline[1:-1] > + > + return [kv_split(v, "=") for v in cmdline.split()] > + > + > +def _generate_linux_default_cmdline(cmdline): > + lines = [] > + cmdline_idx = -1 > + with open("/etc/default/grub") as f: > + for idx, line in enumerate(f): > + line = line.strip() > + lines.extend([line]) > + if line.startswith(_GRUB_CMDLINE_PARAM_NAME): > + cmdline_idx = idx > + if cmdline_idx == -1: > + raise RuntimeError("Invalid GRUB default configuration format") > + > + # write the lines back, replacing one we want > + with open("/etc/default/grub", "w") as f: > + for idx, line in enumerate(lines): > + if idx == cmdline_idx: > + line = cmdline > + f.write(line + "\n") > + > + > +def _find_transparent_hugepage(): > + if not os.path.exists(__KERNEL_TRANSPARENT_HP): > + return None > + value = read_file(__KERNEL_TRANSPARENT_HP) > + m = re.search(r"\[([a-z]+)\]", value) > + if not m: > + raise RuntimeError("BUG: Bad regular expression") > + return m.group(1) > + > + > +class GrubHugepageConfig: > + def __init__(self): > + self.update() > + > + def update(self): > + self.reset() > + > + hugepage_sizes = info.hugepage_sizes_supported > + if len(hugepage_sizes) == 0: > + raise RuntimeError("Hugepages appear to be unsupported") > + cmdline = _find_linux_default_cmdline() > + values = _parse_linux_default_cmdline(cmdline) > + > + # parse values in the list > + self.default_hugepagesz = info.default_hugepage_size > + self.transparent_hugepage = _find_transparent_hugepage() > + sizes = [] > + nrs = [] > + for k, v in values: > + if k == "default_hugepagesz": > + self.default_hugepagesz = human_readable_to_kilobytes(v) > + elif k == "transparent_hugepage": > + self.transparent_hugepage = v > + elif k == "hugepagesz": > + sizes.append(human_readable_to_kilobytes(v)) > + elif k == "hugepages": > + nrs.append(v) > + if len(sizes) != len(nrs): > + raise RuntimeError("GRUB hugepage configuration is wrong") > + detected_hugepages = dict(zip(sizes, map(int, nrs))) > + self.nr_hugepages = {size: detected_hugepages.get(size, 0) > + for size in hugepage_sizes} > + > + def commit(self): > + # perform sanity checks - we can't afford invalid data making it into > + # bootloader config, as that might render user's machine unbootable, so > + # tread really really carefully > + > + # first, check if user didn't add any unexpected hugepage sizes > + configured_sizes = set(self.nr_hugepages.keys()) > + supported_sizes = set(info.hugepage_sizes_supported) > + > + if configured_sizes != supported_sizes: > + diff = configured_sizes.difference(supported_sizes) > + raise ValueError("Unsupported hugepage sizes: %s" % > + [kilobytes_to_human_readable(s) for s in diff]) > + > + # check if default hugepage is one of the supported ones > + if self.default_hugepagesz is not None and\ > + self.default_hugepagesz not in configured_sizes: > + s = kilobytes_to_human_readable(self.default_hugepagesz) > + raise ValueError("Unsupported default hugepage size: %i" % s) > + > + # transparent hugepages support was added in recent kernels, so check > + # if user is trying to set this > + if _find_transparent_hugepage() is None and \ > + self.transparent_hugepage is not None: > + raise ValueError("Transparent hugepages are not unsupported") > + > + # OK, parameters look to be valid - let's roll > + > + # read and parse current cmdline > + cmdline = _find_linux_default_cmdline() > + > + values = _parse_linux_default_cmdline(cmdline) > + > + # clear out old data > + klist = ["transparent_hugepage", "default_hugepagesz", > + "hugepage", "hugepagesz"] > + # iterate over a copy so that we could delete items > + for k, v in values[:]: > + if k in klist: > + values.remove((k, v)) > + > + # generate new cmdline > + cmdline = " ".join([("%s=%s" % (k, v)) if v is not None else k > + for k, v in values]) > + > + # now, populate cmdline with new data > + new_items = [] > + for sz, nr in self.nr_hugepages.items(): > + sz = kilobytes_to_human_readable(sz) > + new_items += "hugepagesz=%s hugepages=%i" % (sz, nr) > + if self.default_hugepagesz is not None: > + new_items += "default_hugepagesz=%i" % self.default_hugepagesz > + if self.transparent_hugepage is not None: > + new_items += "transparent_hugepage=%s" % self.transparent_hugepage > + > + cmdline = "%s %s" % (cmdline, " ".join(new_items)) > + > + # strip any extraneous whitespace we may have added > + cmdline = re.sub(r"\s\s+", " ", cmdline).strip() > + > + # now, put everything back together > + cmdline = '%s="%s"' % (_GRUB_CMDLINE_PARAM_NAME, cmdline) > + > + # write it to config > + _generate_linux_default_cmdline(cmdline) > + > + # finally, update GRUB > + if not run(["update-grub"]): > + raise RuntimeError("Failed to update GRUB") > + self.update() > + > + def reset(self): > + self.nr_hugepages = {} # pagesz: number > + self.default_hugepagesz = None > + self.transparent_hugepage = None > -- > 2.17.1