From patchwork Mon Aug 20 19:49:11 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masayoshi Mizuma X-Patchwork-Id: 959934 X-Patchwork-Delegate: petr.vorel@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=lists.linux.it (client-ip=213.254.12.146; helo=picard.linux.it; envelope-from=ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="icwJL6J0"; dkim-atps=neutral Received: from picard.linux.it (picard.linux.it [213.254.12.146]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 41vPYs0WRzz9s78 for ; Tue, 21 Aug 2018 05:50:57 +1000 (AEST) Received: from picard.linux.it (localhost [IPv6:::1]) by picard.linux.it (Postfix) with ESMTP id 984123E6476 for ; Mon, 20 Aug 2018 21:50:54 +0200 (CEST) X-Original-To: ltp@lists.linux.it Delivered-To: ltp@picard.linux.it Received: from in-6.smtp.seeweb.it (in-6.smtp.seeweb.it [217.194.8.6]) by picard.linux.it (Postfix) with ESMTP id D6F133E640F for ; Mon, 20 Aug 2018 21:50:47 +0200 (CEST) Received: from mail-qt0-x242.google.com (mail-qt0-x242.google.com [IPv6:2607:f8b0:400d:c0d::242]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by in-6.smtp.seeweb.it (Postfix) with ESMTPS id F1C5B1400DA1 for ; Mon, 20 Aug 2018 21:50:46 +0200 (CEST) Received: by mail-qt0-x242.google.com with SMTP id b15-v6so17574460qtp.11 for ; Mon, 20 Aug 2018 12:50:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=/qXaID5ZVm1VzWBu3F6NPOY3IF5sg/314ngi9sHrM2o=; b=icwJL6J0k9vxFcMT73O1QIo1jMFydTIyO74fnBGFSr/v33yDaXVE7L2eCexphfPEJc 3iXzAOg2IMcDS8Z5GAsGjjVIrKZH5w1Tru+7Rt7oFgCuIEvpZEpoIa/m2+8hZcIshHJl GxTqJn26iRohh2ocLI83yGuwI0KUs7nvGQBsPcL+u+iXkq1dkKKh/Gb5buITq9jUtVFU oEWZMK6irE+/7/fyZEPd0QeyJP72ka7Pog65MaCJuNdTfL3za2I9F9J0mYK5WAeDzSDx aUbrz35Q19o57C7pdFjpMrxCr2EXle9F21qOmV2256GpYTFwWyTU0bg6stbAR49maSaE 3kXQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=/qXaID5ZVm1VzWBu3F6NPOY3IF5sg/314ngi9sHrM2o=; b=Eb4XS8SYKNy3yVvBV6QUq0zx3bM3S8866eBAhyUuwGAtbghR/hGbC2mJHnBFUWkMmL HJlXF/KNS67ewLyChiK4tsDZRiqjK+G3EUSaraYX7IMcBAbMfxtlw44ETRD3stR3tj2e BH2bkO6950nLnFJySKZblZuybnL4Jcez7EG4BLpxhdC3hrxRHXkISJ3otrXAYXO8OSv5 M1FBKNdbAv2bHb7dRKehOrDIbxs6iELY1uQe891Gl7vnDiSE4BYAQCMRexPLEaaAYbLQ 2WtpHn+33uNF1h4EfDH6Fwn9u5oFBU7xWab+kalJsNX7rt84MZyfU79pH2jBBBJ5Drlc PC5Q== X-Gm-Message-State: AOUpUlFX6KKEa36qmksrfgqkiFVoIBPd/Z3rq9ZY3D5TPYk1WVCBEA6G bc9xP5CuThUlOKBR/D5/3XfbRLk= X-Google-Smtp-Source: ANB0VdY0E6cx0H5nnIm1+Q5UJH4qpsRTQbmXjep4h/qeVxUKkvK6oPUx8Jd66VM7+NG5bUvEftxjNw== X-Received: by 2002:ac8:488d:: with SMTP id i13-v6mr10206555qtq.235.1534794645776; Mon, 20 Aug 2018 12:50:45 -0700 (PDT) Received: from gabell.bos.redhat.com (nat-pool-bos-t.redhat.com. [66.187.233.206]) by smtp.gmail.com with ESMTPSA id a19-v6sm7321136qta.50.2018.08.20.12.50.45 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 20 Aug 2018 12:50:45 -0700 (PDT) From: Masayoshi Mizuma To: ltp@lists.linux.it Date: Mon, 20 Aug 2018 15:49:11 -0400 Message-Id: <20180820194915.11805-2-msys.mizuma@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180820194915.11805-1-msys.mizuma@gmail.com> References: <20180820194915.11805-1-msys.mizuma@gmail.com> X-Virus-Scanned: clamav-milter 0.99.2 at in-6.smtp.seeweb.it X-Virus-Status: Clean X-Spam-Status: No, score=0.1 required=7.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, SPF_PASS autolearn=disabled version=3.4.0 X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on in-6.smtp.seeweb.it Cc: Masayoshi Mizuma Subject: [LTP] [PATCH 1/5] acpi_hotplug: Add library file for ACPI based cpu and memory hotplug X-BeenThere: ltp@lists.linux.it X-Mailman-Version: 2.1.18 Precedence: list List-Id: Linux Test Project List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it Sender: "ltp" From: Masayoshi Mizuma This file includes some APIs to use ACPI based cpu and memory hotplug. Signed-off-by: Masayoshi Mizuma --- .../hotplug/acpi_hotplug/ACPIHOTPLUG_lib.sh | 310 ++++++++++++++++++ 1 file changed, 310 insertions(+) create mode 100755 testcases/kernel/hotplug/acpi_hotplug/ACPIHOTPLUG_lib.sh diff --git a/testcases/kernel/hotplug/acpi_hotplug/ACPIHOTPLUG_lib.sh b/testcases/kernel/hotplug/acpi_hotplug/ACPIHOTPLUG_lib.sh new file mode 100755 index 000000000..8c5dc1d89 --- /dev/null +++ b/testcases/kernel/hotplug/acpi_hotplug/ACPIHOTPLUG_lib.sh @@ -0,0 +1,310 @@ +#!/bin/sh + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (c) 2018, FUJITSU LIMITED. All rights reserved. + +export HOTPLUGABLE_CONTAINER= +export HOTPLUGABLE_NODES=() +RETRY=5 +RETRY_TIME=60 + +# $1: node number +is_memoryless_node() +{ + local node=$1 + + numactl -H | awk ' + /node '$node' size:/ { + if ($4 == 0) + prine 1 + else + print 0 + }' +} + +# $1: node number +is_movable_node() +{ + local node=$1 + + awk ' + BEGIN { + zone = "" + NotMovableFound = 0 + nextnode = '$node' + 1 + } + /^Node '$node'/{ + zone = $4 + } + /present/ { + if (zone != "") { + if ((zone != "Movable") && ($2 != 0)) { + NotMovableFound = 1 + exit + } + } + } + match($0, "^Node " nextnode) { + exit + } + + END { + if (NotMovableFound == 0) + print 1 + else + print 0 + } + ' /proc/zoneinfo +} + +stop_udev() +{ + systemctl stop systemd-udevd-kernel.socket + systemctl stop systemd-udevd-control.socket + systemctl stop systemd-udevd.service +} + +resume_udev() +{ + systemctl start systemd-udevd.service + systemctl start systemd-udevd-kernel.socket + systemctl start systemd-udevd-control.socket +} + +_setup() +{ + local ACPI_CONTAINERS=() + local ONLINE_CONTAINERS=() + local CPUS=() + local tmp_NODES=() + local NODES=() + local movable_node= + local NOHP_NODES=0 + + ACPI_CONTAINERS=( $(find /sys/devices/LNXSYSTM\:00/ -name 'ACPI0004:*') ) + + ONLINE_CONTAINERS=() + for c in ${ACPI_CONTAINERS[@]}; do + status=$(cat $c/status) + if [[ $status -ne 0 ]]; then + ONLINE_CONTAINERS=( ${ONLINE_CONTAINERS[@]} $c ) + fi + done + + if [[ ${#ONLINE_CONTAINERS[@]} -lt 2 ]]; then + tst_brk TCONF "The number of online ACPI containers is not enough. 2 or more online ACPI containers are needed, but this system has ${#ONLINE_CONTAINERS[@]} contianers." + fi + + for c in ${ONLINE_CONTAINERS[@]}; do + CPUS=( $(find $c -name 'ACPI0007:*' ) ) + tmp_NODES=() + NODES=() + NOHP_NODES=0 + for cpu in ${CPUS[@]}; do + tmp_NODES=( ${tmp_NODES[@]} $(ls $cpu/physical_node/ 2> /dev/null | grep ^node | sed -e 's/node//') ) + done + NODES=( $(echo ${tmp_NODES[@]} | tr ' ' '\n' | sort | uniq ) ) + + # Memory device ID is PNP0C80, however, the memory ID is not used here + # but the node ID is used. + # The hotplugable memory section has ACPI_SRAT_MEM_HOT_PLUGGABLE flag + # and the zone is handled as Movable zone. Following assumes that + # the node has only Movable zone or it is memory less node. + # So using the node ID gets this test cleared rather than using memory ID. + for n in ${NODES[@]}; do + if [[ $(is_movable_node $n) -eq 0 ]] && [[ $(is_memoryless_node $n) -eq 0 ]]; then + NOHP_NODES=1 + break + fi + done + if [[ $NOHP_NODES -eq 0 ]]; then + HOTPLUGABLE_CONTAINER=$(basename $c) + HOTPLUGABLE_NODES=( ${NODES[@]} ) + break + fi + done + + # Some hotplug udev rules may disturb for this test. + # Let's stop them. + stop_udev + + tst_res TINFO "TARGET ACPI CONTANIER: $HOTPLUGABLE_CONTAINER" + tst_res TINFO "TARGET NODES: ${HOTPLUGABLE_NODES[@]}" +} + +_cleanup() +{ + resume_udev +} + +cpu_hp() +{ + local hpop= + local CPUS=( $(echo /sys/bus/acpi/devices/$HOTPLUGABLE_CONTAINER/ACPI0007:*/physical_node/online) ) + + local hp_cpus=${#CPUS[@]} + local current_cpus=$(nproc) + local expected_cpus= + local ACPI_CPU= + local force=0 + local hotplugedcpus=0 + + if [[ $1 == "hotremove" ]]; then + hpop=0 + else + hpop=1 + fi + if [[ $2 == "force" ]]; then + force=1 + fi + + if [[ $hpop -eq 0 ]]; then + expected_cpus=$(( current_cpus - hp_cpus )) + else + expected_cpus=$(( current_cpus + hp_cpus )) + fi + + for cpu in ${CPUS[@]}; do + echo -n $hpop > $cpu 2> /dev/null + ACPI_CPU=$( echo $cpu | sed -e 's#/sys/bus/acpi/devices/ACPI0004:[0-9a-f]\+/\(ACPI0007:.*\)/physical_node/online#\1#') + if [[ $? -ne 0 ]]; then + tst_res TINFO "CPU: $ACPI_CPU $1 failed." + if [[ $force -eq 0 ]]; then + return 1 + fi + else + if [[ $force -ne 0 ]]; then + tst_res TINFO "CPU: $ACPI_CPU $1 successed." + fi + hotplugedcpus=$(( hotplugedcpus + 1 )) + fi + done + + tst_res TINFO "CPU: current: $(nproc) hotpluged: $hotplugedcpus" + if [[ $(nproc) -eq $expected_cpus ]]; then + return 0 + else + return 1 + fi +} + +# $1: node number +# $2: expected memory size (MB) +memhp_result() +{ + local node=$1 + local expected=$2 + local current= + + current=$(numactl -H | awk ' + /^node '$node' size/ { + print $4 + } + ') + + if [[ $current -eq $expected ]]; then + echo 1 + else + echo 0 + fi +} + +memory_hp() +{ + local hpop= + local memory=() + local memhpdone= + local expected= + local block_size_bytes=$(cat /sys/devices/system/memory/block_size_bytes ) + block_size_bytes=$(echo "obase=10;ibase=16;$block_size_bytes" | bc) + local result=0 + local force=0 + local hotplugedsections= + local removable= + + declare -A mem_hotpluged + + if [[ $1 == "hotremove" ]]; then + hpop="offline" + else + hpop="online_movable" + fi + if [[ $2 == "force" ]]; then + force=1 + fi + + for node in ${HOTPLUGABLE_NODES[@]}; do + memory=$(ls /sys/devices/system/node/node$node/ | grep memory | sort -n -r) + for mem in ${memory[@]}; do + if [[ $force -eq 1 ]]; then + echo -n $hpop > /sys/devices/system/node/node$node/$mem/state 2> /dev/null + mem_hotpluged[$node]=$(( mem_hotpluged[$node] + 1 )) + hotplugedsections=$(( hotplugedsections + 1 )) + else + memhpdone=0 + for ((i = 1; i <= RETRY; i++)); do + echo -n $hpop > /sys/devices/system/node/node$node/$mem/state + if [[ $? -eq 0 ]]; then + memhpdone=1 + break + else + removable=$(cat /sys/devices/system/node/node$node/$mem/removable) + if [[ $removable -ne 1 ]]; then + tst_res TINFO "memory: Node: $node section: $mem something wrong..." + return 1 + fi + tst_res TINFO "memory: Node: $node section: $mem $1 failed ($i times). Retry..." + fi + sleep $RETRY_TIME + done + if [[ $memhpdone -eq 0 ]]; then + tst_res TINFO "memory: Node: $node section: $mem $1 failed." + return 1 + else + tst_res TINFO "memory: Node: $node section: $mem $1 successed." + mem_hotpluged[$node]=$(( mem_hotpluged[$node] + 1 )) + hotplugedsections=$(( hotplugedsections + 1 )) + fi + fi + done + done + + for node in ${HOTPLUGABLE_NODES[@]}; do + if [[ $hpop == "offline" ]]; then + expected=0 + else + expected=$(echo "${mem_hotpluged[$node]} * $block_size_bytes/1024/1024" | bc) + fi + if [[ $(memhp_result $node $expected) -ne 1 ]]; then + result=$((result + 1)) + fi + tst_res TINFO "Memory: Node: $node $hotplugedsections sections hotpluged." + done + + return $result +} + +container_hp() +{ + local hpop= + local online_ret=0 + + if [[ $1 == "hotremove" ]]; then + hpop=0 + else + hpop=1 + fi + + echo $hpop > /sys/bus/acpi/devices/$HOTPLUGABLE_CONTAINER/physical_node/online + online_ret=$? + + if [[ $online_ret -ne 0 ]]; then + tst_res TINFO "ACPI container: $HOTPLUGABLE_CONTAINER $1 failed." + numactl -H + return 1 + else + tst_res TINFO "ACPI container: $HOTPLUGABLE_CONTAINER $1 successed." + fi + + return 0 +}