From nobody Wed Nov 24 07:29:19 2021 X-Original-To: dev-commits-ports-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 045C318A14E6; Wed, 24 Nov 2021 07:29:20 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4HzXgz46sVz3N07; Wed, 24 Nov 2021 07:29:19 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 5874A25B42; Wed, 24 Nov 2021 07:29:19 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 1AO7TJ8b092140; Wed, 24 Nov 2021 07:29:19 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 1AO7TJfR092139; Wed, 24 Nov 2021 07:29:19 GMT (envelope-from git) Date: Wed, 24 Nov 2021 07:29:19 GMT Message-Id: <202111240729.1AO7TJfR092139@gitrepo.freebsd.org> To: ports-committers@FreeBSD.org, dev-commits-ports-all@FreeBSD.org, dev-commits-ports-main@FreeBSD.org From: Oleksii Samorukov Subject: git: 40a957b3db98 - main - sysutils/smartmontools: Implement monitoring of the devices behind mrsas RAID List-Id: Commits to the main branch of the FreeBSD ports repository List-Archive: https://lists.freebsd.org/archives/dev-commits-ports-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-ports-main@freebsd.org X-BeenThere: dev-commits-ports-main@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: samm X-Git-Repository: ports X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 40a957b3db989c9d820563005df61464f8a0312d Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1637738959; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=gjF58zUR4JIrhMbQOXPKSb1KOFkmjk1gqrvZ6zLzeCo=; b=Jk4onCyWyJRi9HJbXgxcUxZhf9Yt1lnEn/yAEIqzcJm9zLjZviP8ZL8EEgUnMMBq6NZjsh XQjk0FB1skYpOdeEUWwvj49XMYgjrntBXXzlwfy/AU9hZgibqW9csVMgeDz9UFOKhS6UaL QyNJNbhjZzrBPR7G1fdgWjtthzXo58ocHbMCCh5mfsvvC9CyIu4+SkH6YwNSmMYacwhmse TNvPjbNaZ4OmtWgWGT59JkMUlcQDC6DpssyY5zF/+CJ0KU74VHLdrffUjN8n11LlH+/2g8 9PmZC34sXH2cu70fD0AqWLpdibqpGqEH25FF+AheaYY2eyAdq4gHliSb6+VRCg== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1637738959; a=rsa-sha256; cv=none; b=FhADZkW61jZFCvHYRGA4yt1H1kJuQzIwigLHP4pP7CdIpwUt3KLFQUj/nshABC6turUeN8 TojR4ue/xuLdz5pbXe1aNrK1WYegRXFQAZMyps2GdPg0Id0y5B6w/QyPBgZdyHxwS3sWPK /6jqeI/WOPbxHXREJUr1j0ORh9h+aNI9okopfuDhmzkso+Fqyp8sBBzdrjqvBePi8wBCn1 HhEhAN2wS7asT2SK4pKx9Vh3ybTBPia5u5nYQAhTxMQzVJNTMitU/p4gaOIlQLJMYnsL4Y C4rjy0QhlHzDLKVmR4qdMx5SoCdWtSNbU4iICMra9k6Z/ocvD23d1pa94cBQQg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by samm: URL: https://cgit.FreeBSD.org/ports/commit/?id=40a957b3db989c9d820563005df61464f8a0312d commit 40a957b3db989c9d820563005df61464f8a0312d Author: Oleksii Samorukov AuthorDate: 2021-11-24 07:15:14 +0000 Commit: Oleksii Samorukov CommitDate: 2021-11-24 07:28:58 +0000 sysutils/smartmontools: Implement monitoring of the devices behind mrsas RAID PR: 212211 Reported by: stesin@gmail.com --- sysutils/smartmontools/Makefile | 2 +- sysutils/smartmontools/files/patch-os__freebsd.cpp | 450 +++++++++++++++++++++ sysutils/smartmontools/files/patch-os__freebsd.h | 167 ++++++++ sysutils/smartmontools/files/patch-smartctl.8.in | 47 +++ .../smartmontools/files/patch-smartd.conf.5.in | 56 +++ sysutils/smartmontools/files/smart.in | 3 + 6 files changed, 724 insertions(+), 1 deletion(-) diff --git a/sysutils/smartmontools/Makefile b/sysutils/smartmontools/Makefile index 6b043b9757e7..6600ade6e8fe 100644 --- a/sysutils/smartmontools/Makefile +++ b/sysutils/smartmontools/Makefile @@ -2,7 +2,7 @@ PORTNAME= smartmontools DISTVERSION= 7.2 -PORTREVISION= 2 +PORTREVISION= 3 CATEGORIES= sysutils MASTER_SITES= SF diff --git a/sysutils/smartmontools/files/patch-os__freebsd.cpp b/sysutils/smartmontools/files/patch-os__freebsd.cpp new file mode 100644 index 000000000000..a4abc95ad6b5 --- /dev/null +++ b/sysutils/smartmontools/files/patch-os__freebsd.cpp @@ -0,0 +1,450 @@ +--- os_freebsd.cpp.orig 2020-12-12 21:36:48 UTC ++++ os_freebsd.cpp +@@ -26,6 +26,7 @@ + #endif + #include + #include ++#include + #include + #include + #include +@@ -199,6 +200,9 @@ static const char smartctl_examples[] = + " smartctl -a --device=areca,3/1 /dev/arcmsr0\n" + " (Prints all SMART information for 3rd disk in the 1st enclosure \n" + " on first ARECA RAID controller)\n" ++ " smartctl -a --device=megaraid,3 /dev/mrsas0\n" ++ " (Prints all SMART information for 3rd disk\n" ++ " on first LSI RAID controller)\n" + + ; + +@@ -761,7 +765,240 @@ bool freebsd_escalade_device::ata_pass_through(const a + return true; + } + ++///////////////////////////////////////////////////////////////////////////// ++/// LSI MegaRAID support + ++class freebsd_megaraid_device ++: public /* implements */ scsi_device, ++ public /* extends */ freebsd_smart_device ++{ ++public: ++ freebsd_megaraid_device(smart_interface *intf, const char *name, ++ unsigned int tgt); ++ ++ virtual ~freebsd_megaraid_device(); ++ ++ virtual smart_device * autodetect_open() override; ++ ++ virtual bool open() override; ++ virtual bool close() override; ++ ++ virtual bool scsi_pass_through(scsi_cmnd_io *iop) override; ++ ++private: ++ unsigned int m_disknum; ++ unsigned int m_hba; ++ int m_fd; ++ ++ bool (freebsd_megaraid_device::*pt_cmd)(int cdblen, void *cdb, int dataLen, void *data, ++ int senseLen, void *sense, int report, int direction, int timeout); ++ bool megasas_cmd(int cdbLen, void *cdb, int dataLen, void *data, ++ int senseLen, void *sense, int report, int direction, int timeout); ++}; ++ ++freebsd_megaraid_device::freebsd_megaraid_device(smart_interface *intf, ++ const char *dev_name, unsigned int tgt) ++ : smart_device(intf, dev_name, "megaraid", "megaraid"), ++ freebsd_smart_device(), ++ m_disknum(tgt), m_hba(0), ++ m_fd(-1), pt_cmd(0) ++{ ++ set_info().info_name = strprintf("%s [megaraid_disk_%02d]", dev_name, m_disknum); ++ set_info().dev_type = strprintf("megaraid,%d", tgt); ++} ++ ++freebsd_megaraid_device::~freebsd_megaraid_device() ++{ ++ if (m_fd >= 0) ++ ::close(m_fd); ++} ++ ++smart_device * freebsd_megaraid_device::autodetect_open() ++{ ++ int report = scsi_debugmode; ++ ++ // Open device ++ if (!open()) ++ return this; ++ ++ // The code below is based on smartd.cpp:SCSIFilterKnown() ++ if (strcmp(get_req_type(), "megaraid")) ++ return this; ++ ++ // Get INQUIRY ++ unsigned char req_buff[64] = {0, }; ++ int req_len = 36; ++ if (scsiStdInquiry(this, req_buff, req_len)) { ++ close(); ++ set_err(EIO, "INQUIRY failed"); ++ return this; ++ } ++ ++ int avail_len = req_buff[4] + 5; ++ int len = (avail_len < req_len ? avail_len : req_len); ++ if (len < 36) ++ return this; ++ ++ if (report) ++ pout("Got MegaRAID inquiry.. %s\n", req_buff+8); ++ ++ // Use INQUIRY to detect type ++ { ++ // SAT? ++ ata_device * newdev = smi()->autodetect_sat_device(this, req_buff, len); ++ if (newdev) // NOTE: 'this' is now owned by '*newdev' ++ return newdev; ++ } ++ ++ // Nothing special found ++ return this; ++} ++ ++bool freebsd_megaraid_device::open() ++{ ++ /* Open Device IOCTL node */ ++ if ((m_fd = ::open(get_dev_name(), O_RDWR)) >= 0) { ++ pt_cmd = &freebsd_megaraid_device::megasas_cmd; ++ } ++ else { ++ int err = errno; ++ freebsd_smart_device::close(); ++ return set_err(err, "cannot open %s",get_dev_name()); ++ } ++ set_fd(m_fd); ++ return true; ++} ++ ++bool freebsd_megaraid_device::close() ++{ ++ if (m_fd >= 0) ++ ::close(m_fd); ++ m_fd = -1; m_hba = 0; pt_cmd = 0; ++ set_fd(m_fd); ++ return true; ++} ++ ++bool freebsd_megaraid_device::scsi_pass_through(scsi_cmnd_io *iop) ++{ ++ int report = scsi_debugmode; ++ ++ if (report > 0) { ++ int k, j; ++ const unsigned char * ucp = iop->cmnd; ++ const char * np; ++ char buff[256]; ++ const int sz = (int)sizeof(buff); ++ ++ np = scsi_get_opcode_name(ucp[0]); ++ j = snprintf(buff, sz, " [%s: ", np ? np : ""); ++ for (k = 0; k < (int)iop->cmnd_len; ++k) ++ j += snprintf(&buff[j], (sz > j ? (sz - j) : 0), "%02x ", ucp[k]); ++ if ((report > 1) && ++ (DXFER_TO_DEVICE == iop->dxfer_dir) && (iop->dxferp)) { ++ int trunc = (iop->dxfer_len > 256) ? 1 : 0; ++ ++ snprintf(&buff[j], (sz > j ? (sz - j) : 0), "]\n Outgoing " ++ "data, len=%d%s:\n", (int)iop->dxfer_len, ++ (trunc ? " [only first 256 bytes shown]" : "")); ++ dStrHex(iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1); ++ } ++ else ++ snprintf(&buff[j], (sz > j ? (sz - j) : 0), "]\n"); ++ pout("%s", buff); ++ } ++ ++ // Controller rejects Test Unit Ready ++ if (iop->cmnd[0] == 0x00) ++ return true; ++ ++ if (iop->cmnd[0] == SAT_ATA_PASSTHROUGH_12 || iop->cmnd[0] == SAT_ATA_PASSTHROUGH_16) { ++ // Controller does not return ATA output registers in SAT sense data ++ if (iop->cmnd[2] & (1 << 5)) // chk_cond ++ return set_err(ENOSYS, "ATA return descriptor not supported by controller firmware"); ++ } ++ // SMART WRITE LOG SECTOR causing media errors ++ if ((iop->cmnd[0] == SAT_ATA_PASSTHROUGH_16 // SAT16 WRITE LOG ++ && iop->cmnd[14] == ATA_SMART_CMD && iop->cmnd[3]==0 && iop->cmnd[4] == ATA_SMART_WRITE_LOG_SECTOR) || ++ (iop->cmnd[0] == SAT_ATA_PASSTHROUGH_12 // SAT12 WRITE LOG ++ && iop->cmnd[9] == ATA_SMART_CMD && iop->cmnd[3] == ATA_SMART_WRITE_LOG_SECTOR)) ++ { ++ if(!failuretest_permissive) ++ return set_err(ENOSYS, "SMART WRITE LOG SECTOR may cause problems, try with -T permissive to force"); ++ } ++ if (pt_cmd == NULL) ++ return false; ++ return (this->*pt_cmd)(iop->cmnd_len, iop->cmnd, ++ iop->dxfer_len, iop->dxferp, ++ iop->max_sense_len, iop->sensep, report, iop->dxfer_dir, iop->timeout); ++} ++ ++bool freebsd_megaraid_device::megasas_cmd(int cdbLen, void *cdb, ++ int dataLen, void *data, ++ int senseLen, void * sense, int /*report*/, int dxfer_dir, int timeout) ++{ ++ struct mfi_pass_frame * pthru; ++ struct mfi_ioc_packet uio; ++ ++ pthru = (struct mfi_pass_frame *)&uio.mfi_frame.raw; ++ memset(&uio, 0, sizeof(uio)); ++ ++ pthru->header.cmd = MFI_CMD_PD_SCSI_IO; ++ pthru->header.cmd_status = 0; ++ pthru->header.scsi_status = 0x0; ++ pthru->header.target_id = m_disknum; ++ pthru->header.lun_id = 0; // FIXME, should be bus number? ++ ++ pthru->header.sense_len = senseLen; ++ pthru->sense_addr_lo = (uintptr_t)sense ; ++ pthru->sense_addr_hi = (uintptr_t)((uint64_t)sense >> 32); ++ ++ pthru->header.cdb_len = cdbLen; ++ pthru->header.timeout = timeout; ++ switch (dxfer_dir) { ++ case DXFER_FROM_DEVICE: ++ pthru->header.flags = MFI_FRAME_DIR_READ; ++ break; ++ case DXFER_TO_DEVICE: ++ pthru->header.flags = MFI_FRAME_DIR_WRITE; ++ break; ++ case DXFER_NONE: ++ pthru->header.flags = MFI_FRAME_DIR_NONE; ++ break; ++ } ++ ++ if (dataLen > 0) { ++ uio.mfi_sge_count = 1; ++ uio.mfi_sgl_off = offsetof(struct mfi_pass_frame,sgl); ++ uio.mfi_sgl[0].iov_base = data; ++ uio.mfi_sgl[0].iov_len = dataLen; ++ ++ pthru->header.sg_count = 1; ++ pthru->header.data_len = dataLen; ++ // tested on amd64 kernel in native and 32bit mode ++ pthru->sgl.sg64[0].addr = (intptr_t)data; ++ pthru->sgl.sg64[0].len = (uint32_t)dataLen; ++ } ++ memcpy(pthru->cdb, cdb, cdbLen); ++ ++ uio.mfi_adapter_no = m_hba; ++ uio.mfi_sense_len = senseLen; ++ uio.mfi_sense_off = offsetof(struct mfi_pass_frame, sense_addr_lo); ++ ++ errno = 0; ++ int rc = ioctl(m_fd, MFI_CMD, &uio); ++ ++ if (pthru->header.cmd_status || rc != 0) { ++ if (pthru->header.cmd_status == 12) { ++ return set_err(EIO, "megasas_cmd: Device %d does not exist\n", m_disknum); ++ } ++ return set_err((errno ? errno : EIO), "megasas_cmd result: %d.%d = %d/%d", ++ m_hba, m_disknum, errno, ++ pthru->header.cmd_status); ++ } ++ return true; ++} ++ ++ + ///////////////////////////////////////////////////////////////////////////// + /// Implement Highpoint RAID support with old functions + +@@ -1401,6 +1638,15 @@ smart_device * freebsd_scsi_device::autodetect_open() + return this; + } + ++ // DELL? ++ if (!memcmp(req_buff + 8, "DELL PERC", 12) || !memcmp(req_buff + 8, "MegaRAID", 8) ++ || !memcmp(req_buff + 16, "PERC H", 6) || !memcmp(req_buff + 8, "LSI\0",4) ++ ) { ++ close(); ++ set_err(EINVAL, "DELL or MegaRaid controller, use '-d megaraid,N'"); ++ return this; ++ } ++ + // SAT or USB, skip MFI controllers because of bugs + { + smart_device * newdev = smi()->autodetect_sat_device(this, req_buff, len); +@@ -1453,6 +1699,10 @@ class freebsd_smart_interface (protected) + virtual std::string get_valid_custom_dev_types_str(); + private: + bool get_nvme_devlist(smart_device_list & devlist, const char * type); ++ bool get_dev_megaraid(smart_device_list & devlist); ++ int megaraid_pd_add_list(const char * devname, smart_device_list & devlist); ++ int megaraid_dcmd_cmd(const char * devname, uint32_t opcode, void *buf, ++ size_t bufsize, uint8_t *mbox, size_t mboxlen, uint8_t *statusp); + }; + + +@@ -1775,6 +2025,9 @@ bool freebsd_smart_interface::scan_smart_devices(smart + } + } + ++ // add devices from LSI MegaRaid controllers ++ get_dev_megaraid(devlist); ++ + if (scan_nvme) + get_nvme_devlist(devlist, type); + return true; +@@ -1800,6 +2053,114 @@ bool freebsd_smart_interface::get_nvme_devlist(smart_d + return true; + } + ++// getting devices from LSI SAS MegaRaid, if available ++bool freebsd_smart_interface::get_dev_megaraid(smart_device_list & devlist) ++{ ++ /* Scanning of disks on MegaRaid device */ ++ char ctrlpath[64]; ++ ++ // trying to add devices on first 32 buses, same as StorCLI does ++ for(unsigned i = 0; i <=32; i++) { ++ sprintf(ctrlpath, "%s%u", MFI_CTRLR_PREFIX, i); ++ megaraid_pd_add_list(ctrlpath, devlist); ++ sprintf(ctrlpath, "%s%u", MRSAS_CTRLR_PREFIX, i); ++ megaraid_pd_add_list(ctrlpath, devlist); ++ } ++ return true; ++} ++ ++int ++freebsd_smart_interface::megaraid_dcmd_cmd(const char * devname, uint32_t opcode, void *buf, ++ size_t bufsize, uint8_t *mbox, size_t mboxlen, uint8_t *statusp) ++{ ++ struct mfi_ioc_packet ioc; ++ struct mfi_dcmd_frame * dcmd; ++ ++ if ((mbox != NULL && (mboxlen == 0 || mboxlen > MFI_MBOX_SIZE)) || ++ (mbox == NULL && mboxlen != 0)) ++ { ++ errno = EINVAL; ++ return (-1); ++ } ++ ++ memset(&ioc, 0, sizeof(ioc)); ++ dcmd = (struct mfi_dcmd_frame *)&ioc.mfi_frame.raw; ++ ++ if (mbox) ++ memcpy(dcmd->mbox, mbox, mboxlen); ++ dcmd->header.cmd = MFI_CMD_DCMD; ++ dcmd->header.data_len = bufsize; ++ dcmd->opcode = opcode; ++ ++ if (bufsize > 0) { ++ ioc.mfi_sge_count = 1; ++ ioc.mfi_sgl_off = offsetof(struct mfi_dcmd_frame,sgl); ++ ioc.mfi_sgl[0].iov_base = buf; ++ ioc.mfi_sgl[0].iov_len = bufsize; ++ dcmd->header.sg_count = 1; ++ dcmd->header.data_len = bufsize; ++ // tested on amd64 kernel in native and 32bit mode ++ dcmd->sgl.sg64[0].addr = (intptr_t)buf; ++ dcmd->sgl.sg64[0].len = (uint32_t)bufsize; ++ } ++ ++ int fd; ++ if ((fd = ::open(devname, O_RDWR)) < 0) { ++ return (errno); ++ } ++ // We are using MFI_CMD as it seems to be supported by all LSI BSD drivers ++ int r = ioctl(fd, MFI_CMD, &ioc); ++ ::close(fd); ++ if (r < 0) { ++ return (r); ++ } ++ ++ if (statusp != NULL) ++ *statusp = dcmd->header.cmd_status; ++ else if (dcmd->header.cmd_status != MFI_STAT_OK) { ++ fprintf(stderr, "command %x returned error status %x\n", ++ opcode, dcmd->header.cmd_status); ++ errno = EIO; ++ return (-1); ++ } ++ return (0); ++} ++ ++int ++freebsd_smart_interface::megaraid_pd_add_list(const char * devname, smart_device_list & devlist) ++{ ++ /* ++ * Keep fetching the list in a loop until we have a large enough ++ * buffer to hold the entire list. ++ */ ++ mfi_pd_list * list = 0; ++ for (unsigned list_size = 1024; ; ) { ++ list = reinterpret_cast(realloc(list, list_size)); ++ if (!list) ++ throw std::bad_alloc(); ++ memset(list, 0, list_size); ++ if (megaraid_dcmd_cmd(devname, MFI_DCMD_PD_GET_LIST, list, list_size, NULL, 0, ++ NULL) < 0) ++ { ++ free(list); ++ return (-1); ++ } ++ if (list->size <= list_size) ++ break; ++ list_size = list->size; ++ } ++ ++ // adding all SCSI devices ++ for (unsigned i = 0; i < list->count; i++) { ++ if(list->addr[i].scsi_dev_type) ++ continue; /* non disk device found */ ++ smart_device * dev = new freebsd_megaraid_device(this, devname, list->addr[i].device_id); ++ devlist.push_back(dev); ++ } ++ free(list); ++ return (0); ++} ++ + #if (FREEBSDVER < 800000) // without this build fail on FreeBSD 8 + static char done[USB_MAX_DEVICES]; + +@@ -2034,9 +2395,16 @@ smart_device * freebsd_smart_interface::autodetect_sma + } + } + // device is LSI raid supported by mfi driver +- if(!strncmp("/dev/mfid", test_name, strlen("/dev/mfid"))) +- set_err(EINVAL, "To monitor disks on LSI RAID load mfip.ko module and run 'smartctl -a /dev/passX' to show SMART information"); ++ if(!strncmp("/dev/mfid", test_name, strlen("/dev/mfid"))) { ++ set_err(EINVAL, "To access disks on LSI RAID load mfip.ko and use /dev/passX or use -d 'megaraid,N' with /dev/mfiX devices"); ++ return 0; ++ } + ++ if(!strncmp(MFI_CTRLR_PREFIX, test_name, strlen(MFI_CTRLR_PREFIX)) || !strncmp(MRSAS_CTRLR_PREFIX, test_name, strlen(MRSAS_CTRLR_PREFIX))) { ++ set_err(EINVAL, "To access disks on %s use '-d megaraid,N' device type", test_name); ++ return 0; ++ } ++ + // form /dev/nvme* or nvme* + if(!strncmp("/dev/nvme", test_name, strlen("/dev/nvme"))) + return new freebsd_nvme_device(this, name, "", 0 /* use default nsid */); +@@ -2142,12 +2510,16 @@ smart_device * freebsd_smart_interface::get_custom_sma + return new freebsd_areca_ata_device(this, name, disknum, encnum); + } + ++ if (sscanf(type, "megaraid,%d", &disknum) == 1) { ++ return new freebsd_megaraid_device(this, name, disknum); ++ } ++ + return 0; + } + + std::string freebsd_smart_interface::get_valid_custom_dev_types_str() + { +- return "3ware,N, hpt,L/M/N, cciss,N, areca,N/E" ++ return "3ware,N, hpt,L/M/N, cciss,N, areca,N/E, megaraid,N" + #if FREEBSDVER > 800100 + ", atacam" + #endif diff --git a/sysutils/smartmontools/files/patch-os__freebsd.h b/sysutils/smartmontools/files/patch-os__freebsd.h new file mode 100644 index 000000000000..7bace7bc234d --- /dev/null +++ b/sysutils/smartmontools/files/patch-os__freebsd.h @@ -0,0 +1,167 @@ +--- os_freebsd.h.orig 2018-08-19 18:45:53 UTC ++++ os_freebsd.h +@@ -606,4 +606,164 @@ HPT_PASS_THROUGH_HEADER, *PHPT_PASS_THROUGH_HEADER; + #define __unused __attribute__ ((__unused__)) + #endif + ++// MFI definition from the kernel sources, see sys/dev/mfi ++ ++#define MFI_STAT_OK 0x00 ++#define MFI_DCMD_PD_GET_LIST 0x02010000 ++ ++#define MFI_CTRLR_PREFIX "/dev/mfi" ++#define MRSAS_CTRLR_PREFIX "/dev/mrsas" ++ ++/* ++ * MFI Frame flags ++ */ ++#define MFI_FRAME_POST_IN_REPLY_QUEUE 0x0000 ++#define MFI_FRAME_DONT_POST_IN_REPLY_QUEUE 0x0001 ++#define MFI_FRAME_SGL32 0x0000 ++#define MFI_FRAME_SGL64 0x0002 ++#define MFI_FRAME_SENSE32 0x0000 ++#define MFI_FRAME_SENSE64 0x0004 ++#define MFI_FRAME_DIR_NONE 0x0000 ++#define MFI_FRAME_DIR_WRITE 0x0008 ++#define MFI_FRAME_DIR_READ 0x0010 ++#define MFI_FRAME_DIR_BOTH 0x0018 ++#define MFI_FRAME_IEEE_SGL 0x0020 ++#define MFI_FRAME_FMT "\20" \ ++ "\1NOPOST" \ ++ "\2SGL64" \ ++ "\3SENSE64" \ ++ "\4WRITE" \ ++ "\5READ" \ ++ "\6IEEESGL" ++ ++/* MFI Commands */ ++typedef enum { ++ MFI_CMD_INIT = 0x00, ++ MFI_CMD_LD_READ, ++ MFI_CMD_LD_WRITE, ++ MFI_CMD_LD_SCSI_IO, ++ MFI_CMD_PD_SCSI_IO, ++ MFI_CMD_DCMD, ++ MFI_CMD_ABORT, ++ MFI_CMD_SMP, ++ MFI_CMD_STP ++} mfi_cmd_t; ++ ++/* Scatter Gather elements */ ++struct mfi_sg32 { ++ uint32_t addr; ++ uint32_t len; ++} __packed; ++ ++struct mfi_sg64 { ++ uint64_t addr; ++ uint32_t len; ++} __packed; ++ ++struct mfi_sg_skinny { ++ uint64_t addr; ++ uint32_t len; ++ uint32_t flag; ++} __packed; ++ ++union mfi_sgl { ++ struct mfi_sg32 sg32[1]; ++ struct mfi_sg64 sg64[1]; ++ struct mfi_sg_skinny sg_skinny[1]; ++} __packed; ++ ++/* Message frames. All messages have a common header */ ++struct mfi_frame_header { ++ uint8_t cmd; ++ uint8_t sense_len; ++ uint8_t cmd_status; ++ uint8_t scsi_status; ++ uint8_t target_id; ++ uint8_t lun_id; ++ uint8_t cdb_len; ++ uint8_t sg_count; ++ uint32_t context; ++ /* ++ * pad0 is MSI Specific. Not used by Driver. Zero the value before ++ * sending the command to f/w. ++ */ ++ uint32_t pad0; ++ uint16_t flags; ++#define MFI_FRAME_DATAOUT 0x08 ++#define MFI_FRAME_DATAIN 0x10 ++ uint16_t timeout; ++ uint32_t data_len; ++} __packed; ++ ++#define MFI_PASS_FRAME_SIZE 48 ++struct mfi_pass_frame { ++ struct mfi_frame_header header; ++ uint32_t sense_addr_lo; ++ uint32_t sense_addr_hi; ++ uint8_t cdb[16]; ++ union mfi_sgl sgl; ++} __packed; ++ ++#define MFI_DCMD_FRAME_SIZE 40 ++#define MFI_MBOX_SIZE 12 ++ ++struct mfi_dcmd_frame { ++ struct mfi_frame_header header; ++ uint32_t opcode; ++ uint8_t mbox[MFI_MBOX_SIZE]; ++ union mfi_sgl sgl; ++} __packed; ++ ++#define MAX_IOCTL_SGE 16 ++struct mfi_ioc_packet { ++ uint16_t mfi_adapter_no; ++ uint16_t mfi_pad1; ++ uint32_t mfi_sgl_off; ++ uint32_t mfi_sge_count; ++ uint32_t mfi_sense_off; ++ uint32_t mfi_sense_len; ++ union { ++ uint8_t raw[128]; ++ struct mfi_frame_header hdr; ++ } mfi_frame; ++ ++ struct iovec mfi_sgl[MAX_IOCTL_SGE]; ++} __packed; ++ ++#ifdef COMPAT_FREEBSD32 ++struct mfi_ioc_packet32 { ++ uint16_t mfi_adapter_no; ++ uint16_t mfi_pad1; ++ uint32_t mfi_sgl_off; ++ uint32_t mfi_sge_count; ++ uint32_t mfi_sense_off; ++ uint32_t mfi_sense_len; ++ union { ++ uint8_t raw[128]; ++ struct mfi_frame_header hdr; ++ } mfi_frame; ++ ++ struct iovec32 mfi_sgl[MAX_IOCTL_SGE]; ++} __packed; ++#endif ++ ++struct mfi_pd_address { ++ uint16_t device_id; ++ uint16_t encl_device_id; ++ uint8_t encl_index; ++ uint8_t slot_number; ++ uint8_t scsi_dev_type; /* 0 = disk */ ++ uint8_t connect_port_bitmap; ++ uint64_t sas_addr[2]; ++} __packed; ++ ++#define MAX_SYS_PDS 240 ++struct mfi_pd_list { ++ uint32_t size; ++ uint32_t count; ++ struct mfi_pd_address addr[MAX_SYS_PDS]; ++} __packed; ++ ++#define MFI_CMD _IOWR('M', 1, struct mfi_ioc_packet) ++ + #endif /* OS_FREEBSD_H_ */ diff --git a/sysutils/smartmontools/files/patch-smartctl.8.in b/sysutils/smartmontools/files/patch-smartctl.8.in new file mode 100644 index 000000000000..cc0164ddc90a --- /dev/null +++ b/sysutils/smartmontools/files/patch-smartctl.8.in @@ -0,0 +1,47 @@ +--- smartctl.8.in.orig 2020-12-21 18:34:31 UTC ++++ smartctl.8.in +@@ -478,24 +478,40 @@ this device type is for NVMe disks that are behind a R + bridge. + .Sp + .\" %ENDIF NOT OS Darwin +-.\" %IF OS Linux ++.\" %IF OS Linux FreeBSD + .I marvell + \- [Linux only] interact with SATA disks behind Marvell chip-set + controllers (using the Marvell rather than libata driver). + .Sp + .I megaraid,N +-\- [Linux only] the device consists of one or more SCSI/SAS disks connected ++\- [FreeBSD and Linux only] the device consists of one or more SCSI/SAS disks connected + to a MegaRAID controller. The non-negative integer N (in the range of 0 to +-127 inclusive) denotes which disk on the controller is monitored. ++127 inclusive) denotes which disk on the controller is monitored. This interface ++will also work for Dell PERC controllers. + Use syntax such as: ++.\" %ENDIF OS Linux FreeBSD ++.\" %IF OS ALL ++FreeBSD: ++.\" %ENDIF OS ALL ++.\" %IF OS FreeBSD + .br ++\fBsmartctl \-a \-d megaraid,2 /dev/mfi0\fP ++.br ++\fBsmartctl \-a \-d megaraid,0 /dev/mrsas0\fP ++.br ++.Sp ++.\" %ENDIF OS FreeBSD ++.\" %IF OS ALL ++Linux: ++.\" %ENDIF OS ALL ++.\" %IF OS Linux ++.br + \fBsmartctl \-a \-d megaraid,2 /dev/sda\fP + .br + \fBsmartctl \-a \-d megaraid,0 /dev/sdb\fP + .br + \fBsmartctl \-a \-d megaraid,0 /dev/bus/0\fP + .br +-This interface will also work for Dell PERC controllers. + It is possible to set RAID device name as /dev/bus/N, where N is a SCSI bus + number. + .Sp diff --git a/sysutils/smartmontools/files/patch-smartd.conf.5.in b/sysutils/smartmontools/files/patch-smartd.conf.5.in new file mode 100644 index 000000000000..3544992b45b4 --- /dev/null +++ b/sysutils/smartmontools/files/patch-smartd.conf.5.in @@ -0,0 +1,56 @@ +--- smartd.conf.5.in.orig 2020-11-23 18:25:16 UTC ++++ smartd.conf.5.in +@@ -116,15 +116,27 @@ Section below! + # may become common with SATA disks in SAS and FC + # environments. + /dev/sda \-a \-d sat +-.\" %IF OS Linux ++.\" %IF OS FreeBSD Linux + # +-# Three disks connected to a MegaRAID controller ++# Disks connected to a MegaRAID controller + # Start short self\-tests daily between 1\-2, 2\-3, and + # 3\-4 am. ++.\" %ENDIF OS FreeBSD Linux ++.\" %IF OS Linux ++# Linux: + /dev/sda \-d megaraid,0 \-a \-s S/../.././01 + /dev/sda \-d megaraid,1 \-a \-s S/../.././02 + /dev/sda \-d megaraid,2 \-a \-s S/../.././03 + /dev/bus/0 \-d megaraid,2 \-a \-s S/../.././03 ++.\" %ENDIF OS Linux ++.\" %IF OS FreeBSD ++# FreeBSD: ++/dev/mfi0 \-d megaraid,0 \-a \-s S/../.././01 ++/dev/mfi0 \-d megaraid,1 \-a \-s S/../.././02 ++/dev/mfi0 \-d megaraid,2 \-a \-s S/../.././03 ++/dev/mrsas0 \-d megaraid,2 \-a \-s S/../.././03 ++.\" %ENDIF OS FreeBSD ++.\" %IF OS Linux + # + # Three disks connected to an AacRaid controller + # Start short self\-tests daily between 1\-2, 2\-3, and +@@ -463,18 +475,19 @@ bridge. + \- [Linux only] interact with SATA disks behind Marvell chip-set + controllers (using the Marvell rather than libata driver). + .Sp ++.\" %ENDIF OS FreeBSD Linux ++.\" %IF OS FreeBSD Linux + .I megaraid,N +-\- [Linux only] the device consists of one or more SCSI/SAS disks connected ++\- [Linux and FreeBSD only] the device consists of one or more SCSI/SAS disks connected + to a MegaRAID controller. The non-negative integer N (in the range of 0 to + 127 inclusive) denotes which disk on the controller is monitored. + This interface will also work for Dell PERC controllers. + In log files and email messages this disk will be identified as + megaraid_disk_XXX with XXX in the range from 000 to 127 inclusive. +-It is possible to set RAID device name as /dev/bus/N, where N is a SCSI bus +-number. ++ + Please see the \fBsmartctl\fP(8) man page for further details. + .Sp +-.\" %ENDIF OS Linux ++.\" %ENDIF OS FreeBSD Linux + .\" %IF OS Linux Windows Cygwin + .I aacraid,H,L,ID + \- [Linux, Windows and Cygwin only] the device consists of one or more diff --git a/sysutils/smartmontools/files/smart.in b/sysutils/smartmontools/files/smart.in index d02bc706d447..f9ceea2bfad1 100644 --- a/sysutils/smartmontools/files/smart.in +++ b/sysutils/smartmontools/files/smart.in @@ -48,6 +48,9 @@ case "${daily_status_smart_enable}" in arcmsr*) devflags="-dareca,${device##arcmsr[0-9]*,}" device="/dev/${device%,[0-9]*}" ;; + mrsas*) devflags="-dmegaraid,${device##mrsas[0-9]*,}" + device="/dev/${device%,[0-9]*}" + ;; /*) ;; *) device="/dev/${device}" ;;