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

📄 smartd.cpp

📁 硬盘各项性能的测试,如温度容量版本健康度型号
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    // capability check: ATA error log  if (cfg->errorlog){    int val;    // start with service disabled, and re-enable it if all works OK    cfg->errorlog=0;    cfg->ataerrorcount=0;    if (!cfg->smartval)      PrintOut(LOG_INFO, "Device: %s, no SMART Error log (SMART READ DATA failed); disabling -l error\n", name);    else if (!cfg->permissive && !isSmartErrorLogCapable(cfg->smartval, &drive))      PrintOut(LOG_INFO, "Device: %s, appears to lack SMART Error log; disabling -l error (override with -T permissive Directive)\n", name);    else if ((val=ATAErrorCount(fd, name))<0)      PrintOut(LOG_INFO, "Device: %s, no SMART Error log; remove -l error Directive from smartd.conf\n", name);    else {        cfg->errorlog=1;        cfg->ataerrorcount=val;    }  }    // If we don't need to save SMART data, get rid of it now  if (!retainsmartdata) {    if (cfg->smartval) {      cfg->smartval=CheckFree(cfg->smartval, __LINE__,filenameandversion);      bytes-=sizeof(struct ata_smart_values);    }    if (cfg->smartthres) {      cfg->smartthres=CheckFree(cfg->smartthres, __LINE__,filenameandversion);      bytes-=sizeof(struct ata_smart_thresholds_pvt);    }  }  // capabilities check -- does it support powermode?  if (cfg->powermode) {    int powermode=ataCheckPowerMode(fd);        if (-1 == powermode) {      PrintOut(LOG_CRIT, "Device: %s, no ATA CHECK POWER STATUS support, ignoring -n Directive\n", name);      cfg->powermode=0;    }     else if (powermode!=0 && powermode!=0x80 && powermode!=0xff) {      PrintOut(LOG_CRIT, "Device: %s, CHECK POWER STATUS returned %d, not ATA compliant, ignoring -n Directive\n",	       name, powermode);      cfg->powermode=0;    }  }  // If no tests available or selected, return  if (!(cfg->errorlog    || cfg->selftest || cfg->smartcheck ||         cfg->usagefailed || cfg->prefail  || cfg->usage      ||        cfg->tempdiff    || cfg->tempinfo || cfg->tempcrit     )) {    CloseDevice(fd, name);    return 3;  }    // Do we still have entries available?  while (numdevata+numdevscsi>=ATAandSCSIdevlist_max)    ATAandSCSIdevlist=AllocateMoreSpace(ATAandSCSIdevlist, &ATAandSCSIdevlist_max, "ATA and SCSI devices");    // register device  PrintOut(LOG_INFO,"Device: %s, is SMART capable. Adding to \"monitor\" list.\n",name);      // record number of device, type of device, increment device count  if (cfg->controller_type == CONTROLLER_UNKNOWN)    cfg->controller_type=CONTROLLER_ATA;    // close file descriptor  CloseDevice(fd, name);  return 0;}// Returns 0 if normal SCSI device.// Returns -1 if INQUIRY fails.// Returns 2 if ATA device detected behind SAT layer.// Returns 3 if ATA device detected behind Marvell controller.// Returns 1 if other device detected that we don't want to treat//     as a normal SCSI device.static int SCSIFilterKnown(int fd, char * device){  char req_buff[256];  int req_len, avail_len, len;  memset(req_buff, 0, 96);  req_len = 36;  if (scsiStdInquiry(fd, (unsigned char *)req_buff, req_len)) {    /* Marvell controllers fail on a 36 bytes StdInquiry, but 64 suffices */    /* watch this spot ... other devices could lock up here */    req_len = 64;    if (scsiStdInquiry(fd, (unsigned char *)req_buff, req_len)) {      PrintOut(LOG_INFO, "Device: %s, failed on INQUIRY; skip device\n", device);      // device doesn't like INQUIRY commands      return SCSIFK_FAILED;    }  }  avail_len = req_buff[4] + 5;  len = (avail_len < req_len) ? avail_len : req_len;  if (len >= 36) {    if (0 == strncmp(req_buff + 8, "3ware", 5) || 0 == strncmp(req_buff + 8, "AMCC", 4) ) {      PrintOut(LOG_INFO, "Device %s, please try adding '-d 3ware,N'\n", device);      PrintOut(LOG_INFO, "Device %s, you may need to replace %s with /dev/twaN or /dev/tweN\n", device, device);      return SCSIFK_3WARE;    } else if ((len >= 42) && (0 == strncmp(req_buff + 36, "MVSATA", 6))) {      PrintOut(LOG_INFO, "Device %s: using '-d marvell' for ATA disk with Marvell driver\n", device);      return SCSIFK_MARVELL;    } else if ((avail_len >= 36) &&               (0 == strncmp(req_buff + 8, "ATA     ", 8)) &&	       has_sat_pass_through(fd, 0 /* non-packet dev */)) {      PrintOut(LOG_INFO, "Device %s: using '-d sat' for ATA disk behind SAT layer.\n",               device);      return SCSIFK_SAT;    }  }  return SCSIFK_NORMAL;}// on success, return 0. On failure, return >0.  Never return <0,// please.static int SCSIDeviceScan(cfgfile *cfg, int scanning) {    int k, fd, err, retval;   char *device = cfg->name;  struct scsi_iec_mode_page iec;  UINT8  tBuf[64];  char *mode=NULL;    // should we try to register this as a SCSI device?  switch (cfg->controller_type) {  case CONTROLLER_SCSI:  case CONTROLLER_UNKNOWN:    mode="SCSI";    break;  case CONTROLLER_CCISS:    mode="CCISS";    break;  default:    return 1;  }  // pass user settings on to low-level SCSI commands  con->controller_port=cfg->controller_port;  con->controller_type=cfg->controller_type;    // open the device  if ((fd = OpenDevice(device, mode, scanning)) < 0)    return 1;  PrintOut(LOG_INFO,"Device: %s, opened\n", device);  // early skip if device known and needs to be handled by some other  // device type (e.g. '-d 3ware,<n>')  if ((retval = SCSIFilterKnown(fd, device))) {    CloseDevice(fd, device);    if (retval==SCSIFK_SAT)	// SATA Device behind SAT layer	return SCSIFK_SAT;    if (retval==SCSIFK_MARVELL)        // ATA/SATA device behind Marvell driver	return SCSIFK_MARVELL;        return 2;  }      // check that device is ready for commands. IE stores its stuff on  // the media.  if ((err = scsiTestUnitReady(fd))) {    if (SIMPLE_ERR_NOT_READY == err)      PrintOut(LOG_INFO, "Device: %s, NOT READY (e.g. spun down); skip device\n", device);    else if (SIMPLE_ERR_NO_MEDIUM == err)      PrintOut(LOG_INFO, "Device: %s, NO MEDIUM present; skip device\n", device);    else if (SIMPLE_ERR_BECOMING_READY == err)      PrintOut(LOG_INFO, "Device: %s, BECOMING (but not yet) READY; skip device\n", device);    else      PrintOut(LOG_CRIT, "Device: %s, failed Test Unit Ready [err=%d]\n", device, err);    CloseDevice(fd, device);    return 2;   }    // Badly-conforming USB storage devices may fail this check.  // The response to the following IE mode page fetch (current and  // changeable values) is carefully examined. It has been found  // that various USB devices that malform the response will lock up  // if asked for a log page (e.g. temperature) so it is best to  // bail out now.  if (!(err = scsiFetchIECmpage(fd, &iec, cfg->modese_len)))    cfg->modese_len = iec.modese_len;  else if (SIMPLE_ERR_BAD_FIELD == err)    ;  /* continue since it is reasonable not to support IE mpage */  else { /* any other error (including malformed response) unreasonable */    PrintOut(LOG_INFO,              "Device: %s, Bad IEC (SMART) mode page, err=%d, skip device\n",              device, err);    CloseDevice(fd, device);    return 3;  }    // N.B. The following is passive (i.e. it doesn't attempt to turn on  // smart if it is off). This may change to be the same as the ATA side.  if (!scsi_IsExceptionControlEnabled(&iec)) {    PrintOut(LOG_INFO, "Device: %s, IE (SMART) not enabled, skip device\n"	               "Try 'smartctl -s on %s' to turn on SMART features\n",                         device, device);    CloseDevice(fd, device);    return 3;  }    // Device exists, and does SMART.  Add to list (allocating more space if needed)  while (numdevscsi+numdevata >= ATAandSCSIdevlist_max)    ATAandSCSIdevlist=AllocateMoreSpace(ATAandSCSIdevlist, &ATAandSCSIdevlist_max, "ATA and SCSI devices");    // Flag that certain log pages are supported (information may be  // available from other sources).  if (0 == scsiLogSense(fd, SUPPORTED_LPAGES, 0, tBuf, sizeof(tBuf), 0)) {    for (k = 4; k < tBuf[3] + LOGPAGEHDRSIZE; ++k) {      switch (tBuf[k]) {       case TEMPERATURE_LPAGE:        cfg->TempPageSupported = 1;        break;      case IE_LPAGE:        cfg->SmartPageSupported = 1;        break;      default:        break;      }    }     }    // record type of device  if (cfg->controller_type == CONTROLLER_UNKNOWN)          cfg->controller_type = CONTROLLER_SCSI;    // get rid of allocated memory only needed for ATA devices.  These  // might have been allocated if the user specified Ignore options or  // other ATA-only Attribute-specific options on the DEVICESCAN line.  cfg->monitorattflags = FreeNonZero(cfg->monitorattflags, NMONITOR*32,__LINE__,filenameandversion);  cfg->attributedefs   = FreeNonZero(cfg->attributedefs,   MAX_ATTRIBUTE_NUM,__LINE__,filenameandversion);  cfg->smartval        = FreeNonZero(cfg->smartval,        sizeof(struct ata_smart_values),__LINE__,filenameandversion);  cfg->smartthres      = FreeNonZero(cfg->smartthres,      sizeof(struct ata_smart_thresholds_pvt),__LINE__,filenameandversion);    // Check if scsiCheckIE() is going to work  {    UINT8 asc = 0;    UINT8 ascq = 0;    UINT8 currenttemp = 0;    UINT8 triptemp = 0;        if (scsiCheckIE(fd, cfg->SmartPageSupported, cfg->TempPageSupported,                    &asc, &ascq, &currenttemp, &triptemp)) {      PrintOut(LOG_INFO, "Device: %s, unexpectedly failed to read SMART values\n", device);      cfg->SuppressReport = 1;      if (cfg->tempdiff || cfg->tempinfo || cfg->tempcrit) {        PrintOut(LOG_CRIT, "Device: %s, can't monitor Temperature, ignoring -W Directive\n", device);        cfg->tempdiff = cfg->tempinfo = cfg->tempcrit = 0;      }    }  }    // capability check: self-test-log  if (cfg->selftest){    int retval=scsiCountFailedSelfTests(fd, 0);    if (retval<0) {      // no self-test log, turn off monitoring      PrintOut(LOG_INFO, "Device: %s, does not support SMART Self-Test Log.\n", device);      cfg->selftest=0;      cfg->selflogcount=0;      cfg->selfloghour=0;    }    else {      // register starting values to watch for changes      cfg->selflogcount=SELFTEST_ERRORCOUNT(retval);      cfg->selfloghour =SELFTEST_ERRORHOURS(retval);    }  }    // disable autosave (set GLTSD bit)  if (cfg->autosave==1){    if (scsiSetControlGLTSD(fd, 1, cfg->modese_len))      PrintOut(LOG_INFO,"Device: %s, could not disable autosave (set GLTSD bit).\n",device);    else      PrintOut(LOG_INFO,"Device: %s, disabled autosave (set GLTSD bit).\n",device);  }  // or enable autosave (clear GLTSD bit)  if (cfg->autosave==2){    if (scsiSetControlGLTSD(fd, 0, cfg->modese_len))      PrintOut(LOG_INFO,"Device: %s, could not enable autosave (clear GLTSD bit).\n",device);    else      PrintOut(LOG_INFO,"Device: %s, enabled autosave (cleared GLTSD bit).\n",device);  }    // tell user we are registering device  PrintOut(LOG_INFO, "Device: %s, is SMART capable. Adding to \"monitor\" list.\n", device);    // close file descriptor  CloseDevice(fd, device);  return 0;}// modified treatment of SCSI device behind SAT layerstatic int SCSIandSATDeviceScan(cfgfile *cfg, int scanning) {  int retval = SCSIDeviceScan(cfg, scanning);  cfg->WhichCheckDevice=1; // default SCSI device    if (retval==SCSIFK_SAT) {    // found SATA device behind SAT translation layer	    cfg->controller_type=CONTROLLER_SAT;    cfg->WhichCheckDevice=0; // actually SATA device!    return ATADeviceScan(cfg, scanning);  }  if (retval==SCSIFK_MARVELL) {    // found SATA device behind Marvell controller    cfg->controller_type=CONTROLLER_MARVELL_SATA;    cfg->WhichCheckDevice=0; // actually SATA device!    return ATADeviceScan(cfg, scanning);  }  return retval; }// We compare old and new values of the n'th attribute.  Note that n// is NOT the attribute ID number.. If (Normalized & Raw) equal,// then return 0, else nonzero.int  ATACompareValues(changedattribute_t *delta,                            struct ata_smart_values *newv,                            struct ata_smart_values *oldv,                            struct ata_smart_thresholds_pvt *thresholds,                            int n, char *name){  struct ata_smart_attribute *now,*was;  struct ata_smart_threshold_entry *thre;  unsigned char oldval,newval;  int sameraw;  // check that attribute number in range, and no null pointers  if (n<0 || n>=NUMBER_ATA_SMART_ATTRIBUTES || !newv || !oldv || !thresholds)    return 0;    // pointers to disk's values and vendor's thresholds  now=newv->vendor_attributes+n;  was=oldv->vendor_attributes+n;  thre=thresholds->thres_entries+n;  // consider only valid attributes  if (!now->id || !was->id || !thre->id)    return 0;      // issue warning if they don't have the same ID in all structures:  if ( (now->id != was->id) || (now->id != thre->id) ){    PrintOut(LOG_INFO,"Device: %s, same Attribute has different ID numbers: %d = %d = %d\n",             name, (int)now->id, (int)was->id, (int)thre->id);    return 0;  }  // new and old values of Normalized Attributes  newval=now->current;  oldval=was->current;  // See if the RAW values are unchanged (ie, the same)  if (memcmp(now->raw, was->raw, 6))    sameraw=0;  else    sameraw=1;    // if any values out of the allowed range, or if the values haven't  // changed, return 0  if (!newval || !oldval || newval>0xfe || oldval>0xfe || (oldval==newval && sameraw))    return 0;    // values have changed.  Construct output and return  delta->newval=newval;  delta->oldval=oldval;  delta->id=now->id;  delta->prefail=ATTRIBUTE_FLAGS_PREFAILURE(now->flags);  delta->sameraw=sameraw;  return 1;}// This looks to see if the corresponding bit of the 32 bytes is set.// This wastes a few bytes of storage but eliminates all searching and// sorting functions! Entry is ZERO <==> the attribute ON. Calling// with set=0 tells you if the attrib

⌨️ 快捷键说明

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