From patchwork Fri Dec 1 23:25:49 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Williams X-Patchwork-Id: 10088297 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 0E2F46035E for ; Fri, 1 Dec 2017 23:34:06 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id ED9F42A7B3 for ; Fri, 1 Dec 2017 23:34:05 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E25E22A7C7; Fri, 1 Dec 2017 23:34:05 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from ml01.01.org (ml01.01.org [198.145.21.10]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 5208A2A7B3 for ; Fri, 1 Dec 2017 23:34:05 +0000 (UTC) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 4BA9520352ABD; Fri, 1 Dec 2017 15:29:38 -0800 (PST) X-Original-To: linux-nvdimm@lists.01.org Delivered-To: linux-nvdimm@lists.01.org Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=192.55.52.43; helo=mga05.intel.com; envelope-from=dan.j.williams@intel.com; receiver=linux-nvdimm@lists.01.org Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 40DA921A10961 for ; Fri, 1 Dec 2017 15:29:37 -0800 (PST) Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga105.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 01 Dec 2017 15:34:03 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.45,347,1508828400"; d="scan'208";a="14398055" Received: from dwillia2-desk3.jf.intel.com (HELO dwillia2-desk3.amr.corp.intel.com) ([10.54.39.16]) by orsmga002.jf.intel.com with ESMTP; 01 Dec 2017 15:34:03 -0800 Subject: [ndctl PATCH 15/17] ndctl, test: trigger notifications From: Dan Williams To: linux-nvdimm@lists.01.org Date: Fri, 01 Dec 2017 15:25:49 -0800 Message-ID: <151217074949.28402.12570925189107616348.stgit@dwillia2-desk3.amr.corp.intel.com> In-Reply-To: <151217066885.28402.7962437173336388439.stgit@dwillia2-desk3.amr.corp.intel.com> References: <151217066885.28402.7962437173336388439.stgit@dwillia2-desk3.amr.corp.intel.com> User-Agent: StGit/0.17.1-9-g687f MIME-Version: 1.0 X-BeenThere: linux-nvdimm@lists.01.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: "Linux-nvdimm developer list." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: linux-nvdimm-bounces@lists.01.org Sender: "Linux-nvdimm" X-Virus-Scanned: ClamAV using ClamSMTP Provide a standalone test that can be run against any nvdimm bus to try to trigger SMART notifications. Signed-off-by: Dan Williams --- test/Makefile.am | 4 + test/smart-notify.c | 220 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 224 insertions(+) create mode 100644 test/smart-notify.c diff --git a/test/Makefile.am b/test/Makefile.am index 6698d6cfbab5..85736c3cce09 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -25,6 +25,7 @@ check_PROGRAMS =\ parent-uuid \ multi-pmem \ dax-errors \ + smart-notify \ daxdev-errors if ENABLE_DESTRUCTIVE @@ -100,6 +101,9 @@ device_dax_LDADD = \ $(JSON_LIBS) \ ../libutil.a +smart_notify_SOURCES = smart-notify.c +smart_notify_LDADD = $(LIBNDCTL_LIB) + multi_pmem_SOURCES = \ multi-pmem.c \ $(testcore) \ diff --git a/test/smart-notify.c b/test/smart-notify.c new file mode 100644 index 000000000000..24e9a213836b --- /dev/null +++ b/test/smart-notify.c @@ -0,0 +1,220 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2017 Intel Corporation. All rights reserved. */ +#include +#include +#include +#include +#include +#include + +static void do_notify(struct ndctl_dimm *dimm) +{ + struct ndctl_cmd *s_cmd = ndctl_dimm_cmd_new_smart(dimm); + struct ndctl_cmd *st_cmd = NULL, *sst_cmd = NULL; + unsigned int orig_mtemp, orig_ctemp, orig_spare; + const char *name = ndctl_dimm_get_devname(dimm); + unsigned int alarm, mtemp, ctemp, spare, valid; + int rc, i; + + if (!s_cmd) { + fprintf(stderr, "%s: no smart command support\n", name); + goto out; + } + + rc = ndctl_cmd_submit(s_cmd); + if (rc) { + fprintf(stderr, "%s: smart command failed: %d %s\n", name, + rc, strerror(errno)); + goto out; + } + + valid = ndctl_cmd_smart_get_flags(s_cmd); + alarm = ndctl_cmd_smart_get_alarm_flags(s_cmd); + mtemp = ndctl_cmd_smart_get_media_temperature(s_cmd); + ctemp = ndctl_cmd_smart_get_ctrl_temperature(s_cmd); + spare = ndctl_cmd_smart_get_spares(s_cmd); + fprintf(stderr, "%s: (smart) alarm%s: %#x mtemp%s: %.2f ctemp%s: %.2f spares%s: %d\n", + name, + valid & ND_SMART_ALARM_VALID ? "" : "(invalid)", alarm, + valid & ND_SMART_MTEMP_VALID ? "" : "(invalid)", + ndctl_decode_smart_temperature(mtemp), + valid & ND_SMART_CTEMP_VALID ? "" : "(invalid)", + ndctl_decode_smart_temperature(ctemp), + valid & ND_SMART_SPARES_VALID ? "" : "(invalid)", spare); + + st_cmd = ndctl_dimm_cmd_new_smart_threshold(dimm); + if (!st_cmd) { + fprintf(stderr, "%s: no smart threshold command support\n", name); + goto out; + } + + rc = ndctl_cmd_submit(st_cmd); + if (rc) { + fprintf(stderr, "%s: smart threshold command failed: %d %s\n", + name, rc, strerror(errno)); + goto out; + } + + alarm = ndctl_cmd_smart_threshold_get_alarm_control(st_cmd); + mtemp = ndctl_cmd_smart_threshold_get_media_temperature(st_cmd); + ctemp = ndctl_cmd_smart_threshold_get_ctrl_temperature(st_cmd); + spare = ndctl_cmd_smart_threshold_get_spares(st_cmd); + fprintf(stderr, "%s: (smart thresh) alarm: %#x mtemp: %.2f ctemp: %.2f spares: %d\n", + name, alarm, ndctl_decode_smart_temperature(mtemp), + ndctl_decode_smart_temperature(ctemp), spare); + + orig_mtemp = mtemp; + orig_ctemp = ctemp; + orig_spare = spare; + + sst_cmd = ndctl_dimm_cmd_new_smart_set_threshold(st_cmd); + if (!sst_cmd) { + fprintf(stderr, "%s: no smart set threshold command support\n", name); + goto out; + } + + alarm = ndctl_cmd_smart_threshold_get_supported_alarms(sst_cmd); + if (!alarm) { + fprintf(stderr, "%s: no smart set threshold command support\n", name); + goto out; + } + + + fprintf(stderr, "%s: supported alarms: %#x\n", name, alarm); + + /* + * free the cmd now since we only needed the alarms and will + * create + issue a set_threshold test for each alarm + */ + ndctl_cmd_unref(sst_cmd); + + for (i = 0; i < 3; i++) { + unsigned int set_alarm = 1 << i; + + if (!(alarm & set_alarm)) + continue; + + sst_cmd = ndctl_dimm_cmd_new_smart_set_threshold(st_cmd); + if (!sst_cmd) { + fprintf(stderr, "%s: alloc failed: smart set threshold\n", + name); + goto out; + } + + switch (set_alarm) { + case ND_SMART_SPARE_TRIP: + fprintf(stderr, "%s: set spare threshold: 99\n", name); + ndctl_cmd_smart_threshold_set_spares(sst_cmd, 99); + ndctl_cmd_smart_threshold_set_media_temperature( + sst_cmd, orig_mtemp); + ndctl_cmd_smart_threshold_set_ctrl_temperature( + sst_cmd, orig_ctemp); + break; + case ND_SMART_MTEMP_TRIP: + mtemp = ndctl_cmd_smart_get_media_temperature(s_cmd); + if (mtemp & (1 << 15)) + mtemp *= 2; + else + mtemp /= 2; + fprintf(stderr, "%s: set mtemp threshold: %.2f\n", name, + ndctl_decode_smart_temperature(mtemp)); + ndctl_cmd_smart_threshold_set_spares( + sst_cmd, orig_spare); + ndctl_cmd_smart_threshold_set_media_temperature( + sst_cmd, mtemp); + ndctl_cmd_smart_threshold_set_ctrl_temperature( + sst_cmd, orig_ctemp); + break; + case ND_SMART_CTEMP_TRIP: + ctemp = ndctl_cmd_smart_get_ctrl_temperature(s_cmd); + if (ctemp & (1 << 15)) + ctemp *= 2; + else + ctemp /= 2; + fprintf(stderr, "%s: set ctemp threshold: %.2f\n", name, + ndctl_decode_smart_temperature(ctemp)); + + ndctl_cmd_smart_threshold_set_spares( + sst_cmd, orig_spare); + ndctl_cmd_smart_threshold_set_media_temperature( + sst_cmd, orig_mtemp); + ndctl_cmd_smart_threshold_set_ctrl_temperature( + sst_cmd, ctemp); + + break; + default: + break; + } + + ndctl_cmd_smart_threshold_set_alarm_control(sst_cmd, set_alarm); + rc = ndctl_cmd_submit(sst_cmd); + if (rc) { + fprintf(stderr, "%s: smart set threshold command failed: %d %s\n", + name, rc, strerror(errno)); + goto out; + } + + ndctl_cmd_unref(sst_cmd); + } + + fprintf(stderr, "%s: set thresholds back to defaults\n", name); + sst_cmd = ndctl_dimm_cmd_new_smart_set_threshold(st_cmd); + if (!sst_cmd) { + fprintf(stderr, "%s: alloc failed: smart set threshold\n", + name); + goto out; + } + + rc = ndctl_cmd_submit(sst_cmd); + if (rc) { + fprintf(stderr, "%s: smart set threshold defaults failed: %d %s\n", + name, rc, strerror(errno)); + goto out; + } + +out: + ndctl_cmd_unref(sst_cmd); + ndctl_cmd_unref(st_cmd); + ndctl_cmd_unref(s_cmd); +} + +static void test_dimm_notify(struct ndctl_bus *bus) +{ + struct ndctl_dimm *dimm; + + ndctl_dimm_foreach(bus, dimm) + do_notify(dimm); +} + +int main(int argc, char *argv[]) +{ + struct ndctl_ctx *ctx; + struct ndctl_bus *bus; + int rc = EXIT_FAILURE; + const char *provider; + + rc = ndctl_new(&ctx); + if (rc < 0) + return EXIT_FAILURE; + + if (argc != 2) { + fprintf(stderr, "usage: smart-notify \n"); + goto out; + } + + ndctl_set_log_priority(ctx, LOG_DEBUG); + + provider = argv[1]; + bus = ndctl_bus_get_by_provider(ctx, provider); + if (!bus) { + fprintf(stderr, "smart-notify: unable to find bus (%s)\n", + provider); + goto out; + } + + rc = EXIT_SUCCESS; + test_dimm_notify(bus); +out: + ndctl_unref(ctx); + return rc; +}