Ticket #677: query_device_open.patch
File query_device_open.patch, 7.3 KB (added by , 9 years ago) |
---|
-
dev_interface.cpp
92 92 return this; 93 93 } 94 94 95 bool smart_device::is_powered_down() 96 { 97 return false; 98 } 99 95 100 bool smart_device::owns(const smart_device * /*dev*/) const 96 101 { 97 102 return false; -
dev_interface.h
205 205 virtual smart_device * autodetect_open(); 206 206 207 207 /////////////////////////////////////////////// 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 /////////////////////////////////////////////// 208 219 // Support for tunnelled devices 209 220 210 221 /// Return true if other device is owned by this device. -
os_win32.cpp
1398 1398 1399 1399 virtual bool open(); 1400 1400 1401 virtual bool is_powered_down(); 1402 1401 1403 virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out); 1402 1404 1403 1405 virtual bool ata_identify_is_cached() const; 1404 1406 1405 1407 private: 1406 bool open( int phydrive, int logdrive, const char * options, int port);1408 bool open(bool query_device); 1407 1409 1410 bool open(int phydrive, int logdrive, const char * options, int port, bool query_device); 1411 1408 1412 std::string m_options; 1409 1413 bool m_usr_options; // options set by user? 1410 1414 bool m_admin; // open with admin access? … … 1444 1448 1445 1449 bool win_ata_device::open() 1446 1450 { 1451 // Open device for r/w operations 1452 return open(false); 1453 } 1454 1455 bool win_ata_device::open(bool query_device) 1456 { 1447 1457 const char * name = skipdev(get_dev_name()); int len = strlen(name); 1448 1458 // [sh]d[a-z]([a-z])?(:[saicmfp]+)? => Physical drive 0-701, with options 1449 1459 char drive[2+1] = "", options[8+1] = ""; int n1 = -1, n2 = -1; 1450 1460 if ( sscanf(name, "%*[sh]d%2[a-z]%n:%6[saimfp]%n", drive, &n1, options, &n2) >= 1 1451 1461 && ((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); 1453 1463 } 1454 1464 // [sh]d[a-z],N(:[saicmfp3]+)? => Physical drive 0-701, RAID port N, with options 1455 1465 drive[0] = 0; options[0] = 0; n1 = -1; n2 = -1; … … 1456 1466 unsigned port = ~0; 1457 1467 if ( sscanf(name, "%*[sh]d%2[a-z],%u%n:%7[saimfp3]%n", drive, &port, &n1, options, &n2) >= 2 1458 1468 && 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); 1460 1470 } 1461 1471 // pd<m>,N => Physical drive <m>, RAID port N 1462 1472 int phydrive = -1; port = ~0; n1 = -1; n2 = -1; 1463 1473 if ( sscanf(name, "pd%d%n,%u%n", &phydrive, &n1, &port, &n2) >= 1 1464 1474 && 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); 1466 1476 } 1467 1477 // [a-zA-Z]: => Physical drive behind logical drive 0-25 1468 1478 int logdrive = drive_letter(name); 1469 1479 if (logdrive >= 0) { 1470 return open(-1, logdrive, "", -1 );1480 return open(-1, logdrive, "", -1, query_device); 1471 1481 } 1472 1482 1473 1483 return set_err(EINVAL); … … 1474 1484 } 1475 1485 1476 1486 1477 bool win_ata_device::open(int phydrive, int logdrive, const char * options, int port )1487 bool win_ata_device::open(int phydrive, int logdrive, const char * options, int port, bool query_device) 1478 1488 { 1479 1489 m_phydrive = -1; 1480 1490 char devpath[30]; … … 1487 1497 1488 1498 // Open device 1489 1499 HANDLE h = INVALID_HANDLE_VALUE; 1490 if (!(*options && !options[strspn(options, "fp")]) ) {1500 if (!(*options && !options[strspn(options, "fp")]) && !query_device) { 1491 1501 // Open with admin rights 1492 1502 m_admin = true; 1493 1503 h = CreateFileA(devpath, GENERIC_READ|GENERIC_WRITE, … … 1514 1524 set_fh(h); 1515 1525 1516 1526 // Warn once if admin rights are missing 1517 if (!m_admin ) {1527 if (!m_admin && !query_device) { 1518 1528 static bool noadmin_warning = false; 1519 1529 if (!noadmin_warning) { 1520 1530 pout("Warning: Limited functionality due to missing admin rights\n"); … … 1595 1605 1596 1606 ///////////////////////////////////////////////////////////////////////////// 1597 1607 1608 // Query OS if device is powered up or down. 1609 bool 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 1598 1625 // Interface to ATA devices 1599 1626 bool win_ata_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) 1600 1627 { -
smartctl.cpp
1304 1304 pout("%s: Device of type '%s' [%s] detected\n", 1305 1305 dev->get_info_name(), dev->get_dev_type(), get_protocol_info(dev.get())); 1306 1306 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 1307 1312 // Open device 1308 1313 { 1309 1314 // Save old info -
smartd.cpp
3135 3135 if (cfg.emailtest) 3136 3136 MailWarning(cfg, state, 0, "TEST EMAIL from smartd for device: %s", name); 3137 3137 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 3138 3160 // if we can't open device, fail gracefully rather than hard -- 3139 3161 // perhaps the next time around we'll be able to open it. ATAPI 3140 3162 // cd/dvd devices will hang awaiting media if O_NONBLOCK is not