⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 os_linux.cpp

📁 硬盘各项性能的测试,如温度容量版本健康度型号
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    io_hdr.dxferp = iop->dxferp;    io_hdr.cmdp = iop->cmnd;    io_hdr.sbp = iop->sensep;    /* sg_io_hdr interface timeout has millisecond units. Timeout of 0       defaults to 60 seconds. */    io_hdr.timeout = ((0 == iop->timeout) ? 60 : iop->timeout) * 1000;    switch (iop->dxfer_dir) {        case DXFER_NONE:            io_hdr.dxfer_direction = SG_DXFER_NONE;            break;        case DXFER_FROM_DEVICE:            io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;            break;        case DXFER_TO_DEVICE:            io_hdr.dxfer_direction = SG_DXFER_TO_DEV;            break;        default:            pout("do_scsi_cmnd_io: bad dxfer_dir\n");            return -EINVAL;    }    iop->resp_sense_len = 0;    iop->scsi_status = 0;    iop->resid = 0;    if (ioctl(dev_fd, SG_IO, &io_hdr) < 0) {        if (report && (! unknown))            pout("  SG_IO ioctl failed, errno=%d [%s]\n", errno,                 strerror(errno));        return -errno;    }    iop->resid = io_hdr.resid;    iop->scsi_status = io_hdr.status;    if (report > 0) {        pout("  scsi_status=0x%x, host_status=0x%x, driver_status=0x%x\n"             "  info=0x%x  duration=%d milliseconds  resid=%d\n", io_hdr.status,             io_hdr.host_status, io_hdr.driver_status, io_hdr.info,             io_hdr.duration, io_hdr.resid);        if (report > 1) {            if (DXFER_FROM_DEVICE == iop->dxfer_dir) {                int trunc, len;		len = iop->dxfer_len - iop->resid;		trunc = (len > 256) ? 1 : 0;                if (len > 0) {                    pout("  Incoming data, len=%d%s:\n", len,                         (trunc ? " [only first 256 bytes shown]" : ""));                    dStrHex((const char*)iop->dxferp, (trunc ? 256 : len),                            1);                } else                    pout("  Incoming data trimmed to nothing by resid\n");            }        }    }    if (io_hdr.info | SG_INFO_CHECK) { /* error or warning */        int masked_driver_status = (LSCSI_DRIVER_MASK & io_hdr.driver_status);        if (0 != io_hdr.host_status) {            if ((LSCSI_DID_NO_CONNECT == io_hdr.host_status) ||                (LSCSI_DID_BUS_BUSY == io_hdr.host_status) ||                (LSCSI_DID_TIME_OUT == io_hdr.host_status))                return -ETIMEDOUT;            else                return -EIO;    /* catch all */        }        if (0 != masked_driver_status) {            if (LSCSI_DRIVER_TIMEOUT == masked_driver_status)                return -ETIMEDOUT;            else if (LSCSI_DRIVER_SENSE != masked_driver_status)                return -EIO;        }        if (LSCSI_DRIVER_SENSE == masked_driver_status)            iop->scsi_status = SCSI_STATUS_CHECK_CONDITION;        iop->resp_sense_len = io_hdr.sb_len_wr;        if ((SCSI_STATUS_CHECK_CONDITION == iop->scsi_status) &&            iop->sensep && (iop->resp_sense_len > 0)) {            if (report > 1) {                pout("  >>> Sense buffer, len=%d:\n",                     (int)iop->resp_sense_len);                dStrHex((const char *)iop->sensep, iop->resp_sense_len , 1);            }        }        if (report) {            if (SCSI_STATUS_CHECK_CONDITION == iop->scsi_status) {                if ((iop->sensep[0] & 0x7f) > 0x71)                    pout("  status=%x: [desc] sense_key=%x asc=%x ascq=%x\n",                         iop->scsi_status, iop->sensep[1] & 0xf,                         iop->sensep[2], iop->sensep[3]);                else                    pout("  status=%x: sense_key=%x asc=%x ascq=%x\n",                         iop->scsi_status, iop->sensep[2] & 0xf,                         iop->sensep[12], iop->sensep[13]);            }            else                pout("  status=0x%x\n", iop->scsi_status);        }    }    return 0;#endif}struct linux_ioctl_send_command{    int inbufsize;    int outbufsize;    UINT8 buff[MAX_DXFER_LEN + 16];};/* The Linux SCSI_IOCTL_SEND_COMMAND ioctl is primitive and it doesn't * support: CDB length (guesses it from opcode), resid and timeout. * Patches in Linux 2.4.21 and 2.5.70 to extend SEND DIAGNOSTIC timeout * to 2 hours in order to allow long foreground extended self tests. */static int sisc_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop, int report){    struct linux_ioctl_send_command wrk;    int status, buff_offset;    size_t len;    memcpy(wrk.buff, iop->cmnd, iop->cmnd_len);    buff_offset = iop->cmnd_len;    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 : "<unknown opcode>");        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;            j += 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((const char *)iop->dxferp,                    (trunc ? 256 : iop->dxfer_len) , 1);        }        else            j += snprintf(&buff[j], (sz > j ? (sz - j) : 0), "]\n");        pout(buff);    }    switch (iop->dxfer_dir) {        case DXFER_NONE:            wrk.inbufsize = 0;            wrk.outbufsize = 0;            break;        case DXFER_FROM_DEVICE:            wrk.inbufsize = 0;            if (iop->dxfer_len > MAX_DXFER_LEN)                return -EINVAL;            wrk.outbufsize = iop->dxfer_len;            break;        case DXFER_TO_DEVICE:            if (iop->dxfer_len > MAX_DXFER_LEN)                return -EINVAL;            memcpy(wrk.buff + buff_offset, iop->dxferp, iop->dxfer_len);            wrk.inbufsize = iop->dxfer_len;            wrk.outbufsize = 0;            break;        default:            pout("do_scsi_cmnd_io: bad dxfer_dir\n");            return -EINVAL;    }    iop->resp_sense_len = 0;    iop->scsi_status = 0;    iop->resid = 0;    status = ioctl(dev_fd, SCSI_IOCTL_SEND_COMMAND, &wrk);    if (-1 == status) {        if (report)            pout("  SCSI_IOCTL_SEND_COMMAND ioctl failed, errno=%d [%s]\n",                 errno, strerror(errno));        return -errno;    }    if (0 == status) {        if (report > 0)            pout("  status=0\n");        if (DXFER_FROM_DEVICE == iop->dxfer_dir) {            memcpy(iop->dxferp, wrk.buff, iop->dxfer_len);            if (report > 1) {                int trunc = (iop->dxfer_len > 256) ? 1 : 0;                pout("  Incoming data, len=%d%s:\n", (int)iop->dxfer_len,                     (trunc ? " [only first 256 bytes shown]" : ""));                dStrHex((const char*)iop->dxferp,                        (trunc ? 256 : iop->dxfer_len) , 1);            }        }        return 0;    }    iop->scsi_status = status & 0x7e; /* bits 0 and 7 used to be for vendors */    if (LSCSI_DRIVER_SENSE == ((status >> 24) & 0xf))        iop->scsi_status = SCSI_STATUS_CHECK_CONDITION;    len = (SEND_IOCTL_RESP_SENSE_LEN < iop->max_sense_len) ?                SEND_IOCTL_RESP_SENSE_LEN : iop->max_sense_len;    if ((SCSI_STATUS_CHECK_CONDITION == iop->scsi_status) &&        iop->sensep && (len > 0)) {        memcpy(iop->sensep, wrk.buff, len);        iop->resp_sense_len = len;        if (report > 1) {            pout("  >>> Sense buffer, len=%d:\n", (int)len);            dStrHex((const char *)wrk.buff, len , 1);        }    }    if (report) {        if (SCSI_STATUS_CHECK_CONDITION == iop->scsi_status) {            pout("  status=%x: sense_key=%x asc=%x ascq=%x\n", status & 0xff,                 wrk.buff[2] & 0xf, wrk.buff[12], wrk.buff[13]);        }        else            pout("  status=0x%x\n", status);    }    if (iop->scsi_status > 0)        return 0;    else {        if (report > 0)            pout("  ioctl status=0x%x but scsi status=0, fail with EIO\n",                 status);        return -EIO;      /* give up, assume no device there */    }}/* SCSI command transmission interface function, linux version. * Returns 0 if SCSI command successfully launched and response * received. Even when 0 is returned the caller should check * scsi_cmnd_io::scsi_status for SCSI defined errors and warnings * (e.g. CHECK CONDITION). If the SCSI command could not be issued * (e.g. device not present or timeout) or some other problem * (e.g. timeout) then returns a negative errno value */static int do_normal_scsi_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop,                                  int report){    int res;    /* implementation relies on static sg_io_state variable. If not     * previously set tries the SG_IO ioctl. If that succeeds assume     * that SG_IO ioctl functional. If it fails with an errno value     * other than ENODEV (no device) or permission then assume     * SCSI_IOCTL_SEND_COMMAND is the only option. */    switch (sg_io_state) {    case SG_IO_PRESENT_UNKNOWN:        /* ignore report argument */        if (0 == (res = sg_io_cmnd_io(dev_fd, iop, report, 1))) {            sg_io_state = SG_IO_PRESENT_YES;            return 0;        } else if ((-ENODEV == res) || (-EACCES == res) || (-EPERM == res))            return res;         /* wait until we see a device */        sg_io_state = SG_IO_PRESENT_NO;        /* drop through by design */    case SG_IO_PRESENT_NO:        return sisc_cmnd_io(dev_fd, iop, report);    case SG_IO_PRESENT_YES:        return sg_io_cmnd_io(dev_fd, iop, report, 0);    default:        pout(">>>> do_scsi_cmnd_io: bad sg_io_state=%d\n", sg_io_state);        sg_io_state = SG_IO_PRESENT_UNKNOWN;        return -EIO;    /* report error and reset state */    }}/* Check and call the right interface. Maybe when the do_generic_scsi_cmd_io interface is better   we can take off this crude way of calling the right interface */ int do_scsi_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop, int report) {     switch(con->controller_type)     {         case CONTROLLER_CCISS:#ifdef HAVE_LINUX_CCISS_IOCTL_H             return cciss_io_interface(dev_fd, con->controller_port-1, iop, report);#else             {                 static int warned = 0;                 if (!warned) {                     pout("CCISS support is not available in this build of smartmontools,\n"                          "<linux/cciss_ioctl.h> was not available at build time.\n\n");                     warned = 1;                 }             }             errno = ENOSYS;             return -1;#endif             // not reached             break;         default:             return do_normal_scsi_cmnd_io(dev_fd, iop, report);             // not reached             break;     } }// >>>>>> End of general SCSI specific linux code// prototypevoid printwarning(smart_command_set command);// PURPOSE//   This is an interface routine meant to isolate the OS dependent//   parts of the code, and to provide a debugging interface.  Each//   different port and OS needs to provide it's own interface.  This//   is the linux interface to the 3ware 3w-xxxx driver.  It allows ATA//   commands to be passed through the SCSI driver.// DETAILED DESCRIPTION OF ARGUMENTS//   fd: is the file descriptor provided by open()//   disknum is the disk number (0 to 15) in the RAID array//   escalade_type indicates the type of controller type, and if scsi or char interface is used//   command: defines the different operations.//   select: additional input data if needed (which log, which type of//           self-test).//   data:   location to write output data, if needed (512 bytes).//   Note: not all commands use all arguments.// RETURN VALUES//  -1 if the command failed//   0 if the command succeeded,//   STATUS_CHECK routine://  -1 if the command failed//   0 if the command succeeded and disk SMART status is "OK"//   1 if the command succeeded and disk SMART status is "FAILING"/* 512 is the max payload size: increase if needed */#define BUFFER_LEN_678K      ( sizeof(TW_Ioctl)                  ) // 1044 unpacked, 1041 packed#define BUFFER_LEN_678K_CHAR ( sizeof(TW_New_Ioctl)+512-1        ) // 1539 unpacked, 1536 packed#define BUFFER_LEN_9000      ( sizeof(TW_Ioctl_Buf_Apache)+512-1 ) // 2051 unpacked, 2048 packed#define TW_IOCTL_BUFFER_SIZE ( MAX(MAX(BUFFER_LEN_678K, BUFFER_LEN_9000), BUFFER_LEN_678K_CHAR) )int escalade_command_interface(int fd, int disknum, int escalade_type, smart_command_set command, int select, char *data){  // return value and buffer for ioctl()  int  ioctlreturn, readdata=0;  // Used by both the SCSI and char interfaces  TW_Passthru *passthru=NULL;  char ioctl_buffer[TW_IOCTL_BUFFER_SIZE];  // only used for SCSI device interface  TW_Ioctl   *tw_ioctl=NULL;  TW_Output *tw_output=NULL;  // only used for 6000/7000/8000 char device interface  TW_New_Ioctl *tw_ioctl_char=NULL;  // only used for 9000 character device interface  TW_Ioctl_Buf_Apache *tw_ioctl_apache=NULL;  memset(ioctl_buffer, 0, TW_IOCTL_BUFFER_SIZE);  if (escalade_type==CONTROLLER_3WARE_9000_CHAR) {    tw_ioctl_apache                               = (TW_Ioctl_Buf_Apache *)ioctl_buffer;    tw_ioctl_apache->driver_command.control_code  = TW_IOCTL_FIRMWARE_PASS_THROUGH;    tw_ioctl_apache->driver_command.buffer_length = 512; /* payload size */    passthru                                      = (TW_Passthru *)&(tw_ioctl_apache->firmware_command.command.oldcommand);  }  else if (escalade_type==CONTROLLER_3WARE_678K_CHAR) {    tw_ioctl_char                                 = (TW_New_Ioctl *)ioctl_buffer;    tw_ioctl_char->data_buffer_length             = 512;    passthru                                      = (TW_Passthru *)&(tw_ioctl_char->firmware_command);  }  else if (escalade_type==CONTROLLER_3WARE_678K) {    tw_ioctl                                      = (TW_Ioctl *)ioctl_buffer;    tw_ioctl->cdb[0]                              = TW_IOCTL;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -