From 3bc3de37aed368fe85c4357b8d55a21f99968022 Mon Sep 17 00:00:00 2001 From: Gerold Gruber Date: Tue, 10 Oct 2023 14:01:20 +0200 Subject: [PATCH 1/8] included hddtemp code for SCSI disk temperatures --- src/Makefile.am | 2 +- src/context.h | 6 + src/hddtemp_scsi/get_scsi_temp.c | 137 +++++++++++++++++++ src/hddtemp_scsi/hddtemp.h | 102 ++++++++++++++ src/hddtemp_scsi/scsi.c | 153 +++++++++++++++++++++ src/hddtemp_scsi/scsi.h | 24 ++++ src/hddtemp_scsi/scsicmds.c | 221 +++++++++++++++++++++++++++++++ src/hddtemp_scsi/scsicmds.h | 36 +++++ src/temperature.c | 85 ++++++++---- src/temperature.h | 9 ++ 10 files changed, 749 insertions(+), 26 deletions(-) create mode 100644 src/hddtemp_scsi/get_scsi_temp.c create mode 100644 src/hddtemp_scsi/hddtemp.h create mode 100644 src/hddtemp_scsi/scsi.c create mode 100644 src/hddtemp_scsi/scsi.h create mode 100644 src/hddtemp_scsi/scsicmds.c create mode 100644 src/hddtemp_scsi/scsicmds.h diff --git a/src/Makefile.am b/src/Makefile.am index 4b6a6ba..7d9bb44 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -6,5 +6,5 @@ AM_LDFLAGS = # this lists the binaries to produce, the (non-PHONY, binary) targets in # the previous manual Makefile bin_PROGRAMS = nwipe -nwipe_SOURCES = context.h logging.h options.h prng.h version.h temperature.h nwipe.c gui.c method.h pass.c device.c gui.h isaac_rand/isaac_standard.h isaac_rand/isaac_rand.h isaac_rand/isaac_rand.c isaac_rand/isaac64.h isaac_rand/isaac64.c mt19937ar-cok/mt19937ar-cok.c nwipe.h mt19937ar-cok/mt19937ar-cok.h pass.h device.h logging.c method.c options.c prng.c version.c temperature.c PDFGen/pdfgen.h PDFGen/pdfgen.c create_pdf.c create_pdf.h embedded_images/shred_db.jpg.c embedded_images/shred_db.jpg.h embedded_images/tick_erased.jpg.c embedded_images/tick_erased.jpg.h embedded_images/redcross.c embedded_images/redcross.h hpa_dco.h hpa_dco.c miscellaneous.h miscellaneous.c embedded_images/nwipe_exclamation.jpg.h embedded_images/nwipe_exclamation.jpg.c conf.h conf.c customers.h customers.c +nwipe_SOURCES = context.h logging.h options.h prng.h version.h temperature.h nwipe.c gui.c method.h pass.c device.c gui.h isaac_rand/isaac_standard.h isaac_rand/isaac_rand.h isaac_rand/isaac_rand.c isaac_rand/isaac64.h isaac_rand/isaac64.c mt19937ar-cok/mt19937ar-cok.c nwipe.h mt19937ar-cok/mt19937ar-cok.h pass.h device.h logging.c method.c options.c prng.c version.c temperature.c PDFGen/pdfgen.h PDFGen/pdfgen.c create_pdf.c create_pdf.h embedded_images/shred_db.jpg.c embedded_images/shred_db.jpg.h embedded_images/tick_erased.jpg.c embedded_images/tick_erased.jpg.h embedded_images/redcross.c embedded_images/redcross.h hpa_dco.h hpa_dco.c miscellaneous.h miscellaneous.c embedded_images/nwipe_exclamation.jpg.h embedded_images/nwipe_exclamation.jpg.c conf.h conf.c customers.h customers.c hddtemp_scsi/hddtemp.h hddtemp_scsi/scsi.h hddtemp_scsi/scsicmds.h hddtemp_scsi/get_scsi_temp.c hddtemp_scsi/scsi.c hddtemp_scsi/scsicmds.c nwipe_LDADD = $(PARTED_LIBS) $(LIBCONFIG) diff --git a/src/context.h b/src/context.h index 8d2d12d..d427e29 100644 --- a/src/context.h +++ b/src/context.h @@ -24,6 +24,9 @@ #define CONTEXT_H_ #include "prng.h" +#ifndef __HDDTEMP_H__ +#include "hddtemp_scsi/hddtemp.h" +#endif /* __HDDTEMP_H__ */ typedef enum nwipe_device_t_ { NWIPE_DEVICE_UNKNOWN = 0, // Unknown device. @@ -133,6 +136,8 @@ typedef struct nwipe_context_t_ u64 throughput; // Average throughput in bytes per second. char throughput_txt[13]; // Human readable throughput. u64 verify_errors; // The number of verification errors across all passes. + int templ_has_hwmon_data; // 0 = no hwmon data available, 1 = hwmon data available + int templ_has_scsitemp_data; // 0 = no scsitemp data available, 1 = scsitemp data available char temp1_path[MAX_HWMON_PATH_LENGTH]; // path to temperature variables /sys/class/hwmon/hwmonX/ etc. int temp1_crit; // Critical high drive temperature, 1000000=unitialised, millidegree celsius. int temp1_highest; // Historical highest temperature reached, 1000000=unitialised, millidegree celsius. @@ -148,6 +153,7 @@ typedef struct nwipe_context_t_ int temp1_flash_rate_counter; // used by the gui for timing the flash rate int temp1_flash_rate_status; // 0=blank 1=visible time_t temp1_time; // The time when temperature was last checked, seconds since epoch + struct disk* templ_disk; // Pointer to disk structure for hddtemp SCSI routines int wipe_status; // Wipe finished = 0, wipe in progress = 1, wipe yet to start = -1. char wipe_status_txt[10]; // ERASED, FAILED, ABORTED, INSANITY int spinner_idx; // Index into the spinner character array diff --git a/src/hddtemp_scsi/get_scsi_temp.c b/src/hddtemp_scsi/get_scsi_temp.c new file mode 100644 index 0000000..4b0c40f --- /dev/null +++ b/src/hddtemp_scsi/get_scsi_temp.c @@ -0,0 +1,137 @@ +/* + * get_scsi_temp.c: functions that populate the drive temperature variables + * in SCSI/SAS drives context structure. + * Routines from hddtemp are used here. + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +//#define _LARGEFILE64_SOURCE +//#define _FILE_OFFSET_BITS 64 +#define _BSD_SOURCE + +#include +#include +#include +#include +#include +#include +#include + +#include "nwipe.h" +#include "context.h" +#include "method.h" +#include "device.h" +#include "prng.h" +#include "options.h" +#include "device.h" +#include "logging.h" +#include "temperature.h" +#include "miscellaneous.h" +#include "hddtemp.h" +#include "scsi.h" + +int nwipe_init_scsi_temperature( nwipe_context_t* c ) +{ + +/* dsk anlegen, malloc */ + struct disk *dsk = (struct disk *) malloc(sizeof(struct disk)); + + /* Check the allocation. */ + if( !dsk ) + { + nwipe_perror( errno, __FUNCTION__, "malloc" ); + nwipe_log( NWIPE_LOG_FATAL, "Unable to get memory for disk struct for %s", + c->device_name ); + exit( 1 ) ; + } + + assert(dsk); + + memset(dsk, 0, sizeof(*dsk)); + + /* save the dsk pointer for later use */ + c->templ_disk = dsk; + + /* initialize */ + dsk->drive = c->device_name; + dsk->type = BUS_SCSI; /* we know this as we are only called in this case */ + + errno = 0; + dsk->errormsg[0] = '\0'; + if( (dsk->fd = open(dsk->drive, O_RDONLY | O_NONBLOCK)) < 0) { + snprintf(dsk->errormsg, MAX_ERRORMSG_SIZE, "open: %s\n", strerror(errno)); + dsk->type = ERROR; + return 1; + } + + // sg_logs -t + if( scsi_get_temperature( dsk ) == GETTEMP_SUCCESS ) + { + c->temp1_input = dsk->value; + c->temp1_crit = dsk->refvalue; + } + else + { + nwipe_log( NWIPE_LOG_ERROR, "Can not read SCSI temperature for %s, %s", + dsk->drive, dsk->errormsg ); + free( dsk ); + c->templ_disk = NULL; + return 1; + } + + return 0; +} + + +int nwipe_get_scsi_temperature( nwipe_context_t* c ) +{ + struct disk *dsk; + + dsk = c->templ_disk; + + if( c->templ_disk != NULL && c->templ_disk->fd != -1 ) + { + if( scsi_get_temperature( dsk ) == GETTEMP_SUCCESS ) + { + c->temp1_input = dsk->value; + } + else + { + nwipe_log( NWIPE_LOG_ERROR, "Could not read SCSI temperature for %s, %s", + dsk->drive, dsk->errormsg ); + return 2; + } + } + else + { + nwipe_log( NWIPE_LOG_INFO, "no SCSI temperature reading for %s", dsk->drive ); + return 1; + } + return 0; +} + +void nwipe_shut_scsi_temperature( nwipe_context_t* c ) +{ + if( c->templ_disk->fd != -1 ) + { + close( c->templ_disk->fd ); + } + if( c->templ_disk != NULL ) + { + free( c->templ_disk ); + } + + return; +} diff --git a/src/hddtemp_scsi/hddtemp.h b/src/hddtemp_scsi/hddtemp.h new file mode 100644 index 0000000..58108c2 --- /dev/null +++ b/src/hddtemp_scsi/hddtemp.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2002 Emmanuel VARAGNAT + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __HDDTEMP_H__ +#define __HDDTEMP_H__ + +#include +// #include "db.h" + +//#ifdef ARCH_I386 +//typedef unsigned short u16; +//#endif +#include +typedef __u16 u16; + +#define MAX_ERRORMSG_SIZE 128 +#define DEFAULT_ATTRIBUTE_ID 194 + +#define F_to_C(val) (int)(((double)(val)-32.0)/1.8) +#define C_to_F(val) (int)(((double)(val)*(double)1.8) + (double)32.0) + +enum e_bustype { ERROR = 0, BUS_UNKNOWN, BUS_SATA, BUS_ATA, BUS_SCSI, BUS_TYPE_MAX }; +// enum e_gettemp { +// GETTEMP_ERROR, /* Error */ +// GETTEMP_NOT_APPLICABLE, /* */ +// GETTEMP_UNKNOWN, /* Drive is not in database */ +// GETTEMP_GUESS, /* Not in database, but something was guessed, user must +// check that the temperature returned is correct */ +// GETTEMP_KNOWN, /* Drive appear in database */ +// GETTEMP_NOSENSOR, /* Drive appear in database but is known to have no sensor */ +// GETTEMP_DRIVE_SLEEP, /* Drive is sleeping */ +// GETTEMP_SUCCESS /* read temperature successfully */ +// }; + +#define GETTEMP_SUCCESS 0 +#define GETTEMP_ERROR 1 +#define GETTEMP_NOT_APPLICABLE 2 +#define GETTEMP_UNKNOWN 3 +#define GETTEMP_GUESS 4 +#define GETTEMP_KNOWN 5 +#define GETTEMP_NOSENSOR 6 +#define GETTEMP_DRIVE_SLEEP 7 + +enum e_powermode { + PWM_UNKNOWN, + PWM_ACTIVE, + PWM_SLEEPING, + PWM_STANDBY +}; + + +struct disk { + struct disk * next; + + int fd; + const char * drive; + const char * model; + enum e_bustype type; + int value; /* the drive's temperature */ + int refvalue; /* aka trip temperature */ + struct harddrive_entry * db_entry; + + char errormsg[MAX_ERRORMSG_SIZE]; +// enum e_gettemp ret; + int ret; + time_t last_time; +}; + +struct bustype { + char *name; + int (*probe)(int); + const char *(*model)(int); + enum e_gettemp (*get_temperature)(struct disk *); +}; + + +extern struct bustype * bus[BUS_TYPE_MAX]; +extern char errormsg[MAX_ERRORMSG_SIZE]; +extern int tcp_daemon, debug, quiet, wakeup, af_hint; +extern char separator; +extern long portnum, syslog_interval; +extern char * listen_addr; + +int value_to_unit(struct disk *dsk); +char get_unit(struct disk *dsk); + +#endif diff --git a/src/hddtemp_scsi/scsi.c b/src/hddtemp_scsi/scsi.c new file mode 100644 index 0000000..a65c007 --- /dev/null +++ b/src/hddtemp_scsi/scsi.c @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2002 Emmanuel VARAGNAT + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +/* + * Adapted from a patch sended by : Frederic LOCHON + */ + +// Include file generated by ./configure +#ifdef HAVE_CONFIG_H +#include +#endif + +// Gettext includes +#if ENABLE_NLS +#include +#define _(String) gettext (String) +#else +#define _(String) (String) +#endif + +// Standard includes +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Application specific includes +#include "scsicmds.h" +#include "hddtemp.h" + +/* +static int scsi_probe(int device) { + int bus_num; + + if(ioctl(device, SCSI_IOCTL_GET_BUS_NUMBER, &bus_num)) + return 0; + else + return 1; +} + +static const char *scsi_model (int device) { + unsigned char buf[36]; + + if (scsi_inquiry(device, buf) != 0) + return strdup(_("unknown")); + else { + return strdup(buf + 8); + } +} + */ +int scsi_get_temperature(struct disk *dsk) { + int i; + int tempPage = 0; + unsigned char buffer[1024]; + + /* + on triche un peu + we cheat a little and do not really read form drivedb as SCSI disks are not included there + */ +// dsk->db_entry = (struct harddrive_entry*) malloc(sizeof(struct harddrive_entry)); +// if(dsk->db_entry == NULL) { +// perror("malloc"); +// exit(-1); +// } +// +// dsk->db_entry->regexp = ""; +// dsk->db_entry->description = ""; +// dsk->db_entry->attribute_id = 0; +// dsk->db_entry->unit = 'C'; +// dsk->db_entry->next = NULL; +// +// if (scsi_smartsupport(dsk->fd) == 0) { +// snprintf(dsk->errormsg, MAX_ERRORMSG_SIZE, _("S.M.A.R.T. not available")); +// close(dsk->fd); +// dsk->fd = -1; +// return GETTEMP_NOT_APPLICABLE; +// } +// + /* + Enable SMART + */ + if (scsi_smartDEXCPTdisable(dsk->fd) != 0) { + snprintf(dsk->errormsg, MAX_ERRORMSG_SIZE, "%s", strerror(errno)); + close(dsk->fd); + dsk->fd = -1; + return GETTEMP_ERROR; + } + + /* + Temp. capable + */ + if (scsi_logsense(dsk->fd , SUPPORT_LOG_PAGES, buffer, sizeof(buffer)) != 0) { + snprintf(dsk->errormsg, MAX_ERRORMSG_SIZE, _("log sense failed : %s"), strerror(errno)); + close(dsk->fd); + dsk->fd = -1; + return GETTEMP_ERROR; + } + + for ( i = 4; i < buffer[3] + LOGPAGEHDRSIZE ; i++) { + if (buffer[i] == TEMPERATURE_PAGE) { + tempPage = 1; + break; + } + } + + if(tempPage) { + /* + get temperature (from scsiGetTemp (scsicmd.c)) + */ + if (scsi_logsense(dsk->fd , TEMPERATURE_PAGE, buffer, sizeof(buffer)) != 0) { + snprintf(dsk->errormsg, MAX_ERRORMSG_SIZE, _("log sense failed : %s"), strerror(errno)); + close(dsk->fd); + dsk->fd = -1; + return GETTEMP_ERROR; + } + + dsk->value = buffer[9]; + dsk->refvalue = buffer[15]; + return GETTEMP_SUCCESS; + } else { + return GETTEMP_NOSENSOR; + } +} + +/******************************* + *******************************/ +/* +struct bustype scsi_bus = { + "SCSI", + scsi_probe, + scsi_model, + scsi_get_temperature +}; + */ diff --git a/src/hddtemp_scsi/scsi.h b/src/hddtemp_scsi/scsi.h new file mode 100644 index 0000000..c349e37 --- /dev/null +++ b/src/hddtemp_scsi/scsi.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2002 Emmanuel VARAGNAT + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SCSIC_H_ +#define SCSIC_H_ + +extern struct bustype scsi_bus; + +#endif diff --git a/src/hddtemp_scsi/scsicmds.c b/src/hddtemp_scsi/scsicmds.c new file mode 100644 index 0000000..3449203 --- /dev/null +++ b/src/hddtemp_scsi/scsicmds.c @@ -0,0 +1,221 @@ +/* + * Copyright (C) 2002 Emmanuel VARAGNAT + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +// Include file generated by ./configure +#ifdef HAVE_CONFIG_H +#include +#endif + +// Gettext includes +#if ENABLE_NLS +#include +#define _(String) gettext (String) +#else +#define _(String) (String) +#endif + +// Standard includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Application specific includes +#include "scsicmds.h" + +static void scsi_fixstring(unsigned char *s, int bytecount) +{ + unsigned char *p; + unsigned char *end; + + p = s; + end = s + bytecount; + + /* strip leading blanks */ + while (s != end && *s == ' ') + ++s; + /* compress internal blanks and strip trailing blanks */ + while (s != end && *s) { + if (*s++ != ' ' || (s != end && *s && *s != ' ')) + *p++ = *(s-1); + } + /* wipe out trailing garbage */ + while (p != end) + *p++ = '\0'; +} + +int scsi_SG_IO(int device, unsigned char *cdb, int cdb_len, unsigned char *buffer, int buffer_len, unsigned char *sense, unsigned char sense_len, int dxfer_direction) { + struct sg_io_hdr io_hdr; + + memset(&io_hdr, 0, sizeof(struct sg_io_hdr)); + io_hdr.interface_id = 'S'; + io_hdr.cmdp = cdb; + io_hdr.cmd_len = cdb_len; + io_hdr.dxfer_len = buffer_len; + io_hdr.dxferp = buffer; + io_hdr.mx_sb_len = sense_len; + io_hdr.sbp = sense; + io_hdr.dxfer_direction = dxfer_direction; + io_hdr.timeout = 3000; /* 3 seconds should be ample */ + + return ioctl(device, SG_IO, &io_hdr); +} + +int scsi_SEND_COMMAND(int device, unsigned char *cdb, int cdb_len, unsigned char *buffer, int buffer_len, int dxfer_direction) +{ + unsigned char buf[2048]; + unsigned int inbufsize, outbufsize, ret; + + switch(dxfer_direction) { + case SG_DXFER_FROM_DEV: + inbufsize = 0; + outbufsize = buffer_len; + break; + case SG_DXFER_TO_DEV: + inbufsize = buffer_len; + outbufsize = 0; + break; + default: + inbufsize = 0; + outbufsize = 0; + break; + } + memcpy(buf, &inbufsize , sizeof(inbufsize)); + memcpy(buf + sizeof(inbufsize), &outbufsize , sizeof(outbufsize)); + memcpy(buf + sizeof(inbufsize) + sizeof(outbufsize), cdb, cdb_len); + memcpy(buf + sizeof(inbufsize) + sizeof(outbufsize) + cdb_len, buffer, buffer_len); + + ret = ioctl(device, SCSI_IOCTL_SEND_COMMAND, buf); + + memcpy(buffer, buf + sizeof(inbufsize) + sizeof(outbufsize), buffer_len); + + return ret; +} + +int scsi_command(int device, unsigned char *cdb, int cdb_len, unsigned char *buffer, int buffer_len, int dxfer_direction) +{ + static int SG_IO_supported = -1; + int ret; + + if (SG_IO_supported == 1) + return scsi_SG_IO(device, cdb, cdb_len, buffer, buffer_len, NULL, 0, dxfer_direction); + else if (SG_IO_supported == 0) + return scsi_SEND_COMMAND(device, cdb, cdb_len, buffer, buffer_len, dxfer_direction); + else { + ret = scsi_SG_IO(device, cdb, cdb_len, buffer, buffer_len, NULL, 0, dxfer_direction); + if (ret == 0) { + SG_IO_supported = 1; + return ret; + } else { + SG_IO_supported = 0; + return scsi_SEND_COMMAND(device, cdb, cdb_len, buffer, buffer_len, dxfer_direction); + } + } +} + +int scsi_inquiry(int device, unsigned char *buffer) +{ + unsigned char cdb[6]; + + memset(cdb, 0, sizeof(cdb)); + cdb[0] = INQUIRY; + cdb[4] = 36; /* should be 36 for unsafe devices (like USB mass storage stuff) + * otherwise they can lock up! SPC sections 7.4 and 8.6 */ + + if (scsi_command(device, cdb, sizeof(cdb), buffer, cdb[4], SG_DXFER_FROM_DEV) != 0) + return 1; + else { + scsi_fixstring(buffer + 8, 24); + return 0; + } +} + +int scsi_modesense(int device, unsigned char pagenum, unsigned char *buffer, int buffer_len) { + unsigned char cdb[6]; + int ret; + + memset(cdb, 0, sizeof(cdb)); + cdb[0] = MODE_SENSE; + cdb[2] = pagenum; + cdb[4] = 0xff; + + ret = scsi_command(device, cdb, sizeof(cdb), buffer, buffer_len, SG_DXFER_FROM_DEV); + if (ret == 0) { + if ((buffer[3] + 5) > buffer[0]) /* response length too short */ + return -1; + } + return ret; +} + +int scsi_modeselect(int device, char *buffer) { + unsigned char cdb[6]; + + memset(cdb, 0, sizeof(cdb)); + cdb[0] = MODE_SELECT; + cdb[1] = 0x11; + cdb[4] = buffer[0] + 1; + + memset(buffer, 0, 12); + buffer[3] = 0x08; + buffer[10] = 0x02; + buffer[12] &= 0x3f; + + return scsi_command(device, cdb, sizeof(cdb), buffer, cdb[4], SG_DXFER_TO_DEV); +} + +int scsi_logsense(int device, int pagenum, unsigned char *buffer, int buffer_len) { + unsigned char cdb[10]; + + memset(cdb, 0, sizeof(cdb)); + cdb[0] = LOG_SENSE; + cdb[2] = 0x40 | pagenum; + cdb[7] = 0x04; + + return scsi_command(device, cdb, sizeof(cdb), buffer, buffer_len, SG_DXFER_FROM_DEV); +} + +int scsi_smartsupport(int device) { + unsigned char buf[255]; + + if (scsi_modesense (device, EXCEPTIONS_CONTROL_PAGE, buf, sizeof(buf)) != 0) + return 0; + else + return (buf[14] & 0x08) == 0; +} + +int scsi_smartDEXCPTdisable(int device) { + unsigned char buf[255]; + + if (scsi_modesense (device, EXCEPTIONS_CONTROL_PAGE, buf, sizeof(buf)) != 0) + return 1; + + if (buf[14] & 0x08) { + buf[14] &= 0xf7; + buf[15] = 0x04; + return scsi_modeselect (device, buf); + } + else + return 0; +} + diff --git a/src/hddtemp_scsi/scsicmds.h b/src/hddtemp_scsi/scsicmds.h new file mode 100644 index 0000000..46cd268 --- /dev/null +++ b/src/hddtemp_scsi/scsicmds.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2002 Emmanuel VARAGNAT + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#ifndef SCSICMDS_H_ +#define SCSICMDS_H_ + +#define SUPPORT_LOG_PAGES 0x00 +#define TEMPERATURE_PAGE 0x0d +#define EXCEPTIONS_CONTROL_PAGE 0x1c +#define LOGPAGEHDRSIZE 4 + +int scsi_SG_IO(int device, unsigned char *cdb, int cdb_len, unsigned char *buffer, int buffer_len, unsigned char *sense, unsigned char sense_len, int dxfer_direction); +int scsi_inquiry(int device, unsigned char *buffer); +int scsi_modesense(int device, unsigned char pagenum, unsigned char *buffer, int buffer_len); +int scsi_modeselect(int device, char *buffer); +int scsi_logsense(int device, int pagenum, unsigned char *buffer, int buffer_len); +int scsi_smartsupport(int device); +int scsi_smartDEXCPTdisable(int device); + +#endif diff --git a/src/temperature.c b/src/temperature.c index 36cbd72..15c90e1 100644 --- a/src/temperature.c +++ b/src/temperature.c @@ -59,6 +59,7 @@ int nwipe_init_temperature( nwipe_context_t* c ) * so it can display appropriate information when a * device is unable to provide temperature data */ + c->templ_has_hwmon_data = 0; c->temp1_crit = NO_TEMPERATURE_DATA; c->temp1_highest = NO_TEMPERATURE_DATA; c->temp1_input = NO_TEMPERATURE_DATA; @@ -187,6 +188,7 @@ int nwipe_init_temperature( nwipe_context_t* c ) } /* Copy the hwmon path to the drive context structure */ strcpy( c->temp1_path, dirpath_hwmonX ); + c->templ_has_hwmon_data = 1; } } closedir( dir2 ); @@ -195,6 +197,20 @@ int nwipe_init_temperature( nwipe_context_t* c ) } closedir( dir ); } + /* if no hwmon data available try scsi access (SAS Disks are known to be not working in hwmon */ + if( c->templ_has_hwmon_data == 0 && ( c->device_type == NWIPE_DEVICE_SAS || c->device_type == NWIPE_DEVICE_SCSI ) ) + { + nwipe_log( NWIPE_LOG_NOTICE, "no hwmon data for %s, try to get SCSI data", c->device_name ); + if( nwipe_init_scsi_temperature( c ) == 0 ) + { + c->templ_has_scsitemp_data = 1; + nwipe_log( NWIPE_LOG_INFO, "got SCSI temperature data for %s", c->device_name ); + } + { + c->templ_has_scsitemp_data = 0; + nwipe_log( NWIPE_LOG_INFO, "got no SCSI temperature data for %s", c->device_name ); + } + } return 0; } @@ -224,37 +240,56 @@ void nwipe_update_temperature( nwipe_context_t* c ) int idx; int result; - for( idx = 0; idx < NUMBER_OF_FILES; idx++ ) + /* try to get temperatures from hwmon, standard */ + if( c->templ_has_hwmon_data == 1 ) { - /* Construct the full path including filename */ - strcpy( path, c->temp1_path ); - strcat( path, "/" ); - strcat( path, &( temperature_label[idx][0] ) ); - - /* Open the file */ - if( ( fptr = fopen( path, "r" ) ) != NULL ) + for( idx = 0; idx < NUMBER_OF_FILES; idx++ ) { - /* Acquire data until we reach a newline */ - result = fscanf( fptr, "%[^\n]", temperature ); + /* Construct the full path including filename */ + strcpy( path, c->temp1_path ); + strcat( path, "/" ); + strcat( path, &( temperature_label[idx][0] ) ); - /* Convert numeric ascii to binary integer */ - *( temperature_pcontext[idx] ) = atoi( temperature ); - - /* Divide by 1000 to get degrees celsius */ - *( temperature_pcontext[idx] ) = *( temperature_pcontext[idx] ) / 1000; - - if( nwipe_options.verbose ) + /* Open the file */ + if( ( fptr = fopen( path, "r" ) ) != NULL ) { - nwipe_log( NWIPE_LOG_NOTICE, "hwmon: %s %dC", path, *( temperature_pcontext[idx] ) ); + /* Acquire data until we reach a newline */ + result = fscanf( fptr, "%[^\n]", temperature ); + + /* Convert numeric ascii to binary integer */ + *( temperature_pcontext[idx] ) = atoi( temperature ); + + /* Divide by 1000 to get degrees celsius */ + *( temperature_pcontext[idx] ) = *( temperature_pcontext[idx] ) / 1000; + + if( nwipe_options.verbose ) + { + nwipe_log( NWIPE_LOG_NOTICE, "hwmon: %s %dC", path, *( temperature_pcontext[idx] ) ); + } + + fclose( fptr ); } - - fclose( fptr ); - } - else - { - if( nwipe_options.verbose ) + else { - nwipe_log( NWIPE_LOG_NOTICE, "hwmon: Unable to open %s", path ); + if( nwipe_options.verbose ) + { + nwipe_log( NWIPE_LOG_NOTICE, "hwmon: Unable to open %s", path ); + } + } + } + } + else + { + /* alternative method to get temperature from SCSI/SAS disks */ + if( c->device_type == NWIPE_DEVICE_SAS || c->device_type == NWIPE_DEVICE_SCSI ) + { + if( c->templ_has_scsitemp_data == 1 ) + { + nwipe_log( NWIPE_LOG_NOTICE, "hddtemp: get temperature for %s", c->device_name ); + if( nwipe_get_scsi_temperature( c ) != 0 ) + { + nwipe_log( NWIPE_LOG_ERROR, "get_scsi_temperature error" ); + } } } } diff --git a/src/temperature.h b/src/temperature.h index a5d4def..0a60707 100644 --- a/src/temperature.h +++ b/src/temperature.h @@ -35,6 +35,15 @@ int nwipe_init_temperature( nwipe_context_t* ); void nwipe_update_temperature( nwipe_context_t* ); +/** + * Workaround for obtaining temperatures from SCSI/SAS drives + * @param pointer to a drive context + * @return returns 0 on success < 1 on error + */ +int nwipe_init_scsi_temperature( nwipe_context_t* ); +int nwipe_get_scsi_temperature( nwipe_context_t* ); +void nwipe_shut_scsi_temperature( nwipe_context_t* ); + /** * This function is normally called only once. It's called after both the * nwipe_init_temperature() function and nwipe_update_temperature() From 97efd12b93d5fd1f424eef5a6f14bc607b005070 Mon Sep 17 00:00:00 2001 From: Gerold Gruber Date: Tue, 10 Oct 2023 14:32:32 +0200 Subject: [PATCH 2/8] fixes --- src/temperature.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/temperature.c b/src/temperature.c index 15c90e1..b0e1e08 100644 --- a/src/temperature.c +++ b/src/temperature.c @@ -206,6 +206,7 @@ int nwipe_init_temperature( nwipe_context_t* c ) c->templ_has_scsitemp_data = 1; nwipe_log( NWIPE_LOG_INFO, "got SCSI temperature data for %s", c->device_name ); } + else { c->templ_has_scsitemp_data = 0; nwipe_log( NWIPE_LOG_INFO, "got no SCSI temperature data for %s", c->device_name ); @@ -240,6 +241,11 @@ void nwipe_update_temperature( nwipe_context_t* c ) int idx; int result; + time_t nwipe_time_now = time( NULL ); + if( nwipe_time_now - c->temp1_time < 60 ) + { + return; + } /* try to get temperatures from hwmon, standard */ if( c->templ_has_hwmon_data == 1 ) { From 47112c4de2816a676ed43d008e1f6063baff41e2 Mon Sep 17 00:00:00 2001 From: Gerold Gruber Date: Wed, 11 Oct 2023 00:05:57 +0200 Subject: [PATCH 3/8] some code cleaning, time debugging added --- src/gui.c | 12 +++++++ src/hddtemp_scsi/get_scsi_temp.c | 4 +++ src/hddtemp_scsi/hddtemp.h | 11 ------- src/hddtemp_scsi/scsi.c | 54 +++----------------------------- 4 files changed, 21 insertions(+), 60 deletions(-) diff --git a/src/gui.c b/src/gui.c index b948a65..f9a23f5 100644 --- a/src/gui.c +++ b/src/gui.c @@ -823,9 +823,21 @@ void nwipe_gui_select( int count, nwipe_context_t** c ) wprintw( main_window, "[%s] ", c[i + offset]->device_size_text ); + // NOTE temporary timing code + clock_t t; + t = clock(); + /* Read the drive temperature values */ nwipe_update_temperature( c[i + offset] ); + // NOTE temporary timing code + t = clock() - t; + double time_taken = ( (double) t ) / CLOCKS_PER_SEC; // in seconds + nwipe_log( NWIPE_LOG_INFO, + "nwipe_update_temperature() took %f seconds for %s", + time_taken, + c[i + offset]->device_name ); + /* print the temperature */ wprintw_temperature( c[i + offset] ); diff --git a/src/hddtemp_scsi/get_scsi_temp.c b/src/hddtemp_scsi/get_scsi_temp.c index 4b0c40f..a935d3f 100644 --- a/src/hddtemp_scsi/get_scsi_temp.c +++ b/src/hddtemp_scsi/get_scsi_temp.c @@ -3,6 +3,8 @@ * in SCSI/SAS drives context structure. * Routines from hddtemp are used here. * + * Author: Gerold Gruber + * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, version 2. @@ -42,6 +44,8 @@ #include "hddtemp.h" #include "scsi.h" +int scsi_get_temperature( struct disk * ); + int nwipe_init_scsi_temperature( nwipe_context_t* c ) { diff --git a/src/hddtemp_scsi/hddtemp.h b/src/hddtemp_scsi/hddtemp.h index 58108c2..6565991 100644 --- a/src/hddtemp_scsi/hddtemp.h +++ b/src/hddtemp_scsi/hddtemp.h @@ -35,17 +35,6 @@ typedef __u16 u16; #define C_to_F(val) (int)(((double)(val)*(double)1.8) + (double)32.0) enum e_bustype { ERROR = 0, BUS_UNKNOWN, BUS_SATA, BUS_ATA, BUS_SCSI, BUS_TYPE_MAX }; -// enum e_gettemp { -// GETTEMP_ERROR, /* Error */ -// GETTEMP_NOT_APPLICABLE, /* */ -// GETTEMP_UNKNOWN, /* Drive is not in database */ -// GETTEMP_GUESS, /* Not in database, but something was guessed, user must -// check that the temperature returned is correct */ -// GETTEMP_KNOWN, /* Drive appear in database */ -// GETTEMP_NOSENSOR, /* Drive appear in database but is known to have no sensor */ -// GETTEMP_DRIVE_SLEEP, /* Drive is sleeping */ -// GETTEMP_SUCCESS /* read temperature successfully */ -// }; #define GETTEMP_SUCCESS 0 #define GETTEMP_ERROR 1 diff --git a/src/hddtemp_scsi/scsi.c b/src/hddtemp_scsi/scsi.c index a65c007..1308595 100644 --- a/src/hddtemp_scsi/scsi.c +++ b/src/hddtemp_scsi/scsi.c @@ -18,6 +18,9 @@ /* * Adapted from a patch sended by : Frederic LOCHON */ +/* + * Adapted for use with nwipe by : Gerold Gruber + */ // Include file generated by ./configure #ifdef HAVE_CONFIG_H @@ -47,26 +50,6 @@ #include "scsicmds.h" #include "hddtemp.h" -/* -static int scsi_probe(int device) { - int bus_num; - - if(ioctl(device, SCSI_IOCTL_GET_BUS_NUMBER, &bus_num)) - return 0; - else - return 1; -} - -static const char *scsi_model (int device) { - unsigned char buf[36]; - - if (scsi_inquiry(device, buf) != 0) - return strdup(_("unknown")); - else { - return strdup(buf + 8); - } -} - */ int scsi_get_temperature(struct disk *dsk) { int i; int tempPage = 0; @@ -75,26 +58,9 @@ int scsi_get_temperature(struct disk *dsk) { /* on triche un peu we cheat a little and do not really read form drivedb as SCSI disks are not included there + original code omitted as there is no need for it in the context of nwipe */ -// dsk->db_entry = (struct harddrive_entry*) malloc(sizeof(struct harddrive_entry)); -// if(dsk->db_entry == NULL) { -// perror("malloc"); -// exit(-1); -// } -// -// dsk->db_entry->regexp = ""; -// dsk->db_entry->description = ""; -// dsk->db_entry->attribute_id = 0; -// dsk->db_entry->unit = 'C'; -// dsk->db_entry->next = NULL; -// -// if (scsi_smartsupport(dsk->fd) == 0) { -// snprintf(dsk->errormsg, MAX_ERRORMSG_SIZE, _("S.M.A.R.T. not available")); -// close(dsk->fd); -// dsk->fd = -1; -// return GETTEMP_NOT_APPLICABLE; -// } -// + /* Enable SMART */ @@ -141,13 +107,3 @@ int scsi_get_temperature(struct disk *dsk) { } } -/******************************* - *******************************/ -/* -struct bustype scsi_bus = { - "SCSI", - scsi_probe, - scsi_model, - scsi_get_temperature -}; - */ From 68a6002ff165ca8d4ffaa79b4b7d41a32b5e63fe Mon Sep 17 00:00:00 2001 From: Gerold Gruber Date: Thu, 12 Oct 2023 12:37:32 +0200 Subject: [PATCH 4/8] temp statistics for SAS drives --- src/hddtemp_scsi/get_scsi_temp.c | 22 ++++++++++++++++++++++ src/hddtemp_scsi/scsi.c | 20 ++++++++++++++++++-- src/temperature.c | 11 ++++++++++- 3 files changed, 50 insertions(+), 3 deletions(-) diff --git a/src/hddtemp_scsi/get_scsi_temp.c b/src/hddtemp_scsi/get_scsi_temp.c index a935d3f..12271b3 100644 --- a/src/hddtemp_scsi/get_scsi_temp.c +++ b/src/hddtemp_scsi/get_scsi_temp.c @@ -110,6 +110,28 @@ int nwipe_get_scsi_temperature( nwipe_context_t* c ) if( scsi_get_temperature( dsk ) == GETTEMP_SUCCESS ) { c->temp1_input = dsk->value; + if( c->temp1_max == NO_TEMPERATURE_DATA ) + { + c->temp1_max = c->temp1_input; + } + else + { + if( c->temp1_input > c->temp1_max ) + { + c->temp1_max = c->temp1_input; + } + } + if( c->temp1_min == NO_TEMPERATURE_DATA ) + { + c->temp1_min = c->temp1_input; + } + else + { + if( c->temp1_input < c->temp1_min ) + { + c->temp1_min = c->temp1_input; + } + } } else { diff --git a/src/hddtemp_scsi/scsi.c b/src/hddtemp_scsi/scsi.c index 1308595..ab00ad6 100644 --- a/src/hddtemp_scsi/scsi.c +++ b/src/hddtemp_scsi/scsi.c @@ -99,11 +99,27 @@ int scsi_get_temperature(struct disk *dsk) { return GETTEMP_ERROR; } - dsk->value = buffer[9]; + if( (int)buffer[7] == 2 ) /* PARAMETER LENGTH */ + { + dsk->value = buffer[9]; + } + else + { + snprintf(dsk->errormsg, MAX_ERRORMSG_SIZE, _("parameter length unexpected: %d"), (int)buffer[7] ); + return GETTEMP_UNKNOWN; + } dsk->refvalue = buffer[15]; + if( (int)buffer[13] == 2 ) /* PARAMETER LENGTH */ + { + dsk->refvalue = buffer[15]; + } + else + { + snprintf(dsk->errormsg, MAX_ERRORMSG_SIZE, _("parameter ref length unexpected: %d"), (int)buffer[13] ); + return GETTEMP_UNKNOWN; + } return GETTEMP_SUCCESS; } else { return GETTEMP_NOSENSOR; } } - diff --git a/src/temperature.c b/src/temperature.c index b0e1e08..6bc8db4 100644 --- a/src/temperature.c +++ b/src/temperature.c @@ -291,7 +291,16 @@ void nwipe_update_temperature( nwipe_context_t* c ) { if( c->templ_has_scsitemp_data == 1 ) { - nwipe_log( NWIPE_LOG_NOTICE, "hddtemp: get temperature for %s", c->device_name ); + if( nwipe_options.verbose ) + { + nwipe_log( NWIPE_LOG_NOTICE, "hddtemp: %s temp1_crit %dC", c->device_name, c->temp1_crit ); + nwipe_log( NWIPE_LOG_NOTICE, "hddtemp: %s temp1_highest %dC", c->device_name, c->temp1_highest ); + nwipe_log( NWIPE_LOG_NOTICE, "hddtemp: %s temp1_input %dC", c->device_name, c->temp1_input ); + nwipe_log( NWIPE_LOG_NOTICE, "hddtemp: %s temp1_lcrit %dC", c->device_name, c->temp1_lcrit ); + nwipe_log( NWIPE_LOG_NOTICE, "hddtemp: %s temp1_lowest %dC", c->device_name, c->temp1_lowest ); + nwipe_log( NWIPE_LOG_NOTICE, "hddtemp: %s temp1_max %dC", c->device_name, c->temp1_max ); + nwipe_log( NWIPE_LOG_NOTICE, "hddtemp: %s temp1_min %dC", c->device_name, c->temp1_min ); + } if( nwipe_get_scsi_temperature( c ) != 0 ) { nwipe_log( NWIPE_LOG_ERROR, "get_scsi_temperature error" ); From 6a92755cf204df4de37bf983ba77aaf7fb62ed1c Mon Sep 17 00:00:00 2001 From: Gerold Gruber Date: Thu, 12 Oct 2023 21:15:31 +0200 Subject: [PATCH 5/8] detect and display if disk is a SSD --- src/context.h | 1 + src/device.c | 32 ++++++++++++++++++++++++++++---- src/device.h | 2 +- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/context.h b/src/context.h index d427e29..59f1a00 100644 --- a/src/context.h +++ b/src/context.h @@ -107,6 +107,7 @@ typedef struct nwipe_context_t_ struct stat device_stat; // The device file state from fstat(). nwipe_device_t device_type; // Indicates an IDE, SCSI, or Compaq SMART device in enumerated form (int) char device_type_str[14]; // Indicates an IDE, SCSI, USB etc as per nwipe_device_t but in ascii + int device_is_ssd; // 0 = no SSD, 1 = is a SSD char device_serial_no[21]; // Serial number(processed, 20 characters plus null termination) of the device. int device_target; // The device target. diff --git a/src/device.c b/src/device.c index ed1ead9..550192c 100644 --- a/src/device.c +++ b/src/device.c @@ -128,6 +128,7 @@ int check_device( nwipe_context_t*** c, PedDevice* dev, int dcount ) int r; char tmp_serial[21]; nwipe_device_t bus; + int is_ssd; int check_HPA; // a flag that indicates whether we check for a HPA on this device bus = 0; @@ -150,7 +151,7 @@ int check_device( nwipe_context_t*** c, PedDevice* dev, int dcount ) if( nwipe_options.nousb ) { /* retrieve bus and drive serial number, HOWEVER we are only interested in the bus at this time */ - r = nwipe_get_device_bus_type_and_serialno( dev->path, &bus, tmp_serial ); + r = nwipe_get_device_bus_type_and_serialno( dev->path, &bus, &is_ssd, tmp_serial ); /* See nwipe_get_device_bus_type_and_serialno() function for meaning of these codes */ if( r == 0 || ( r >= 3 && r <= 6 ) ) @@ -265,7 +266,8 @@ int check_device( nwipe_context_t*** c, PedDevice* dev, int dcount ) trim( (char*) next_device->device_serial_no ); /* if we couldn't obtain serial number by using the above method .. try this */ - r = nwipe_get_device_bus_type_and_serialno( next_device->device_name, &next_device->device_type, tmp_serial ); + r = nwipe_get_device_bus_type_and_serialno( + next_device->device_name, &next_device->device_type, &next_device->device_is_ssd, tmp_serial ); /* If serial number & bus retrieved (0) OR unsupported USB bus identified (5) */ if( r == 0 || r == 5 ) @@ -358,6 +360,14 @@ int check_device( nwipe_context_t*** c, PedDevice* dev, int dcount ) check_HPA = 1; break; } + if( next_device->device_is_ssd ) + { + strcpy( next_device->device_type_str + 4, "-SSD" ); + } + else + { + strcpy( next_device->device_type_str + 4, " " ); + } if( strlen( (const char*) next_device->device_serial_no ) ) { @@ -457,10 +467,10 @@ char* trim( char* str ) return str; } -int nwipe_get_device_bus_type_and_serialno( char* device, nwipe_device_t* bus, char* serialnumber ) +int nwipe_get_device_bus_type_and_serialno( char* device, nwipe_device_t* bus, int* is_ssd, char* serialnumber ) { /* The caller provides a string that contains the device, i.e. /dev/sdc, also a pointer - * to a integer (bus type) and thirdly a 21 byte + * to an integer (bus type), another pointer to an integer (is_ssd), and finally a 21 byte * character string which this function populates with the serial number (20 characters + null terminator). * * The function populates the bus integer and serial number strings for the given device. @@ -803,6 +813,20 @@ int nwipe_get_device_bus_type_and_serialno( char* device, nwipe_device_t* bus, c } } } + if( strstr( result, "rotation rate:" ) != 0 ) + { + /* strip any leading or trailing spaces and left justify, +15 is the length of "Rotation Rate:" */ + trim( &result[15] ); + for( idx = 15; result[idx]; idx++ ) + { + result[idx] = tolower( result[idx] ); + } + + if( strncmp( &result[15], "solid state device", 19 ) == 0 ) + { + *is_ssd = 1; + } + } } /* close */ diff --git a/src/device.h b/src/device.h index 489c74c..50c04c1 100644 --- a/src/device.h +++ b/src/device.h @@ -40,7 +40,7 @@ int nwipe_device_scan( nwipe_context_t*** c ); // Find devices that we can wipe */ int nwipe_device_get( nwipe_context_t*** c, char** devnamelist, int ndevnames ); // Get info about devices to wipe. -int nwipe_get_device_bus_type_and_serialno( char*, nwipe_device_t*, char* ); +int nwipe_get_device_bus_type_and_serialno( char*, nwipe_device_t*, int*, char* ); void strip_CR_LF( char* ); void determine_disk_capacity_nomenclature( u64, char* ); void remove_ATA_prefix( char* ); From b6f97454f1c16ce26c99539a876b0e2a01bf8532 Mon Sep 17 00:00:00 2001 From: Gerold Gruber Date: Thu, 12 Oct 2023 21:44:51 +0200 Subject: [PATCH 6/8] more temperatur limit fake for SAS disks --- src/hddtemp_scsi/get_scsi_temp.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/hddtemp_scsi/get_scsi_temp.c b/src/hddtemp_scsi/get_scsi_temp.c index 12271b3..31d8a8f 100644 --- a/src/hddtemp_scsi/get_scsi_temp.c +++ b/src/hddtemp_scsi/get_scsi_temp.c @@ -85,11 +85,17 @@ int nwipe_init_scsi_temperature( nwipe_context_t* c ) { c->temp1_input = dsk->value; c->temp1_crit = dsk->refvalue; + c->temp1_lcrit = -40; /* just to give it a value with some kind of sense */ + c->temp1_highest = dsk->value; + c->temp1_lowest = dsk->value; + c->temp1_min = dsk->value; + c->temp1_max = dsk->value; } else { nwipe_log( NWIPE_LOG_ERROR, "Can not read SCSI temperature for %s, %s", dsk->drive, dsk->errormsg ); + close( dsk->fd ); free( dsk ); c->templ_disk = NULL; return 1; @@ -119,11 +125,13 @@ int nwipe_get_scsi_temperature( nwipe_context_t* c ) if( c->temp1_input > c->temp1_max ) { c->temp1_max = c->temp1_input; + c->temp1_highest = c->temp1_input; } } if( c->temp1_min == NO_TEMPERATURE_DATA ) { c->temp1_min = c->temp1_input; + c->temp1_lowest = c->temp1_input; } else { From de887ea6eeb8d61ed96877bc013f57217319636b Mon Sep 17 00:00:00 2001 From: Gerold Gruber Date: Thu, 12 Oct 2023 22:15:18 +0200 Subject: [PATCH 7/8] get better timing information for temperature retrieval --- src/temperature.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/temperature.c b/src/temperature.c index 6bc8db4..4c73530 100644 --- a/src/temperature.c +++ b/src/temperature.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "nwipe.h" #include "context.h" @@ -216,6 +217,12 @@ int nwipe_init_temperature( nwipe_context_t* c ) return 0; } +float timedifference_msec( struct timeval tv_start, struct timeval tv_end ) +{ + /* helper function for time measurement in msec */ + return ( tv_end.tv_sec - tv_start.tv_sec ) * 1000.0f + ( tv_end.tv_usec - tv_start.tv_usec ) / 1000.0f; +} + void nwipe_update_temperature( nwipe_context_t* c ) { /* For the given drive context obtain the path to it's hwmon temperature settings @@ -240,12 +247,20 @@ void nwipe_update_temperature( nwipe_context_t* c ) FILE* fptr; int idx; int result; + struct timeval tv_start; + struct timeval tv_end; + float delta_t; + /* avoid being called more often than 1x per 60 seconds */ time_t nwipe_time_now = time( NULL ); if( nwipe_time_now - c->temp1_time < 60 ) { return; } + + /* measure time it takes to get the temperatures */ + gettimeofday( &tv_start, 0 ); + /* try to get temperatures from hwmon, standard */ if( c->templ_has_hwmon_data == 1 ) { @@ -314,6 +329,10 @@ void nwipe_update_temperature( nwipe_context_t* c ) * every 60 seconds */ c->temp1_time = time( NULL ); + gettimeofday( &tv_end, 0 ); + delta_t = timedifference_msec( tv_start, tv_end ); + nwipe_log( NWIPE_LOG_NOTICE, "get temperature for %s took %f ms", c->device_name, delta_t ); + return; } From 53d91f4b8b617c0e25d59199f2a691845d91bc42 Mon Sep 17 00:00:00 2001 From: Gerold Gruber Date: Fri, 13 Oct 2023 07:44:56 +0200 Subject: [PATCH 8/8] fix lowest --- src/hddtemp_scsi/get_scsi_temp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hddtemp_scsi/get_scsi_temp.c b/src/hddtemp_scsi/get_scsi_temp.c index 31d8a8f..434e1d6 100644 --- a/src/hddtemp_scsi/get_scsi_temp.c +++ b/src/hddtemp_scsi/get_scsi_temp.c @@ -131,13 +131,13 @@ int nwipe_get_scsi_temperature( nwipe_context_t* c ) if( c->temp1_min == NO_TEMPERATURE_DATA ) { c->temp1_min = c->temp1_input; - c->temp1_lowest = c->temp1_input; } else { if( c->temp1_input < c->temp1_min ) { c->temp1_min = c->temp1_input; + c->temp1_lowest = c->temp1_input; } } }