Ticket #677: query_device_open.patch

File query_device_open.patch, 7.3 KB (added by Thomas Gatterweh, 8 years ago)
  • dev_interface.cpp

     
    9292  return this;
    9393}
    9494
     95bool smart_device::is_powered_down()
     96{
     97  return false;
     98}
     99
    95100bool smart_device::owns(const smart_device * /*dev*/) const
    96101{
    97102  return false;
  • dev_interface.h

     
    205205  virtual smart_device * autodetect_open();
    206206
    207207  ///////////////////////////////////////////////
     208  // Support for checking power mode reported by operating system
     209
     210  /// Early test if device is powered up or down.
     211  /// Can be used without calling 'open()' first!
     212  /// Return true when device is powered down, false when
     213  /// powered up. If this function is not implemented or
     214  /// the mode cannot be determined, return false.
     215  /// Default implementation returns false.
     216  virtual bool is_powered_down();
     217
     218  ///////////////////////////////////////////////
    208219  // Support for tunnelled devices
    209220
    210221  /// Return true if other device is owned by this device.
  • os_win32.cpp

     
    13981398
    13991399  virtual bool open();
    14001400
     1401  virtual bool is_powered_down();
     1402
    14011403  virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out);
    14021404
    14031405  virtual bool ata_identify_is_cached() const;
    14041406
    14051407private:
    1406   bool open(int phydrive, int logdrive, const char * options, int port);
     1408  bool open(bool query_device);
    14071409
     1410  bool open(int phydrive, int logdrive, const char * options, int port, bool query_device);
     1411
    14081412  std::string m_options;
    14091413  bool m_usr_options; // options set by user?
    14101414  bool m_admin; // open with admin access?
     
    14441448
    14451449bool win_ata_device::open()
    14461450{
     1451  // Open device for r/w operations
     1452  return open(false);
     1453}
     1454
     1455bool win_ata_device::open(bool query_device)
     1456{
    14471457  const char * name = skipdev(get_dev_name()); int len = strlen(name);
    14481458  // [sh]d[a-z]([a-z])?(:[saicmfp]+)? => Physical drive 0-701, with options
    14491459  char drive[2+1] = "", options[8+1] = ""; int n1 = -1, n2 = -1;
    14501460  if (   sscanf(name, "%*[sh]d%2[a-z]%n:%6[saimfp]%n", drive, &n1, options, &n2) >= 1
    14511461      && ((n1 == len && !options[0]) || n2 == len)                                   ) {
    1452     return open(sdxy_to_phydrive(drive), -1, options, -1);
     1462    return open(sdxy_to_phydrive(drive), -1, options, -1, query_device);
    14531463  }
    14541464  // [sh]d[a-z],N(:[saicmfp3]+)? => Physical drive 0-701, RAID port N, with options
    14551465  drive[0] = 0; options[0] = 0; n1 = -1; n2 = -1;
     
    14561466  unsigned port = ~0;
    14571467  if (   sscanf(name, "%*[sh]d%2[a-z],%u%n:%7[saimfp3]%n", drive, &port, &n1, options, &n2) >= 2
    14581468      && port < 32 && ((n1 == len && !options[0]) || n2 == len)                                  ) {
    1459     return open(sdxy_to_phydrive(drive), -1, options, port);
     1469    return open(sdxy_to_phydrive(drive), -1, options, port, query_device);
    14601470  }
    14611471  // pd<m>,N => Physical drive <m>, RAID port N
    14621472  int phydrive = -1; port = ~0; n1 = -1; n2 = -1;
    14631473  if (   sscanf(name, "pd%d%n,%u%n", &phydrive, &n1, &port, &n2) >= 1
    14641474      && phydrive >= 0 && ((n1 == len && (int)port < 0) || (n2 == len && port < 32))) {
    1465     return open(phydrive, -1, "", (int)port);
     1475    return open(phydrive, -1, "", (int)port, query_device);
    14661476  }
    14671477  // [a-zA-Z]: => Physical drive behind logical drive 0-25
    14681478  int logdrive = drive_letter(name);
    14691479  if (logdrive >= 0) {
    1470     return open(-1, logdrive, "", -1);
     1480    return open(-1, logdrive, "", -1, query_device);
    14711481  }
    14721482
    14731483  return set_err(EINVAL);
     
    14741484}
    14751485
    14761486
    1477 bool win_ata_device::open(int phydrive, int logdrive, const char * options, int port)
     1487bool win_ata_device::open(int phydrive, int logdrive, const char * options, int port, bool query_device)
    14781488{
    14791489  m_phydrive = -1;
    14801490  char devpath[30];
     
    14871497
    14881498  // Open device
    14891499  HANDLE h = INVALID_HANDLE_VALUE;
    1490   if (!(*options && !options[strspn(options, "fp")])) {
     1500  if (!(*options && !options[strspn(options, "fp")]) && !query_device) {
    14911501    // Open with admin rights
    14921502    m_admin = true;
    14931503    h = CreateFileA(devpath, GENERIC_READ|GENERIC_WRITE,
     
    15141524  set_fh(h);
    15151525
    15161526  // Warn once if admin rights are missing
    1517   if (!m_admin) {
     1527  if (!m_admin && !query_device) {
    15181528    static bool noadmin_warning = false;
    15191529    if (!noadmin_warning) {
    15201530      pout("Warning: Limited functionality due to missing admin rights\n");
     
    15951605
    15961606/////////////////////////////////////////////////////////////////////////////
    15971607
     1608// Query OS if device is powered up or down.
     1609bool win_ata_device::is_powered_down()
     1610{
     1611  // To check power mode, we open device for query operations only.
     1612  // Opening for SMART r/w operations can already spin up the disk.
     1613  bool self_open = !is_open();
     1614  if (self_open)
     1615    if (!open(true))
     1616      return false;
     1617  int rc = get_device_power_state(get_fh());
     1618  if (self_open)
     1619    close();
     1620  return !rc;
     1621}
     1622
     1623/////////////////////////////////////////////////////////////////////////////
     1624
    15981625// Interface to ATA devices
    15991626bool win_ata_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
    16001627{
  • smartctl.cpp

     
    13041304    pout("%s: Device of type '%s' [%s] detected\n",
    13051305         dev->get_info_name(), dev->get_dev_type(), get_protocol_info(dev.get()));
    13061306
     1307  if (dev->is_ata() && ataopts.powermode>=2 && dev->is_powered_down()) {
     1308    pout( "%s: Device is in %s mode, exit(%d)\n", dev->get_info_name(), "STANDBY (OS)", FAILPOWER );
     1309    return FAILPOWER;
     1310  }
     1311
    13071312  // Open device
    13081313  {
    13091314    // Save old info
  • smartd.cpp

     
    31353135  if (cfg.emailtest)
    31363136    MailWarning(cfg, state, 0, "TEST EMAIL from smartd for device: %s", name);
    31373137
     3138  // User may have requested (with the -n Directive) to leave the disk
     3139  // alone if it is in idle or standby mode.  In this case check the
     3140  // power mode first before opening the device for full access,
     3141  // and exit without check if disk is reported in standby.
     3142  if (cfg.powermode>=2 && !state.powermodefail) {
     3143    // Note that 'is_powered_down()' handles opening the device itself, and
     3144    // can be used before calling 'open()' (that's the whole point of 'is_powered_down()'!).
     3145    if (atadev->is_powered_down())
     3146    {
     3147      // skip at most powerskipmax checks
     3148      if (!cfg.powerskipmax || state.powerskipcnt<cfg.powerskipmax) {
     3149        // report first only except if state has changed, avoid waking up system disk
     3150        if ((!state.powerskipcnt || state.lastpowermodeskipped != -1) && !cfg.powerquiet) {
     3151          PrintOut(LOG_INFO, "Device: %s, is in %s mode, suspending checks\n", name, "STANDBY (OS)");
     3152          state.lastpowermodeskipped = -1;
     3153        }
     3154        state.powerskipcnt++;
     3155        return 0;
     3156      }
     3157    }
     3158  }
     3159
    31383160  // if we can't open device, fail gracefully rather than hard --
    31393161  // perhaps the next time around we'll be able to open it.  ATAPI
    31403162  // cd/dvd devices will hang awaiting media if O_NONBLOCK is not