diff --git a/smartmontools/CHANGELOG b/smartmontools/CHANGELOG index 1c940645443817476815866742e1b23a929f39dc..e0fcb7f31b0a9270f628f9e9e53888c8bd7ab28a 100644 --- a/smartmontools/CHANGELOG +++ b/smartmontools/CHANGELOG @@ -43,6 +43,12 @@ NOTES FOR FUTURE RELEASES: see TODO file. <DEVELOPERS: ADDITIONS TO THE CHANGE LOG GO JUST BELOW HERE, PLEASE> + [CF] Linux: Allow smartd 'DEVICESCAN -d sat' (ticket #13). + Detects (S)ATA devices behind a standard SAT layer + (Vendor ID: "ATA "), but not USB bridges with SAT support. + Only added for backward compatibility with 5.38. + No longer needed as 'DEVICESCAN' without '-d' includes these devices. + [CF] Add USB ID of Seagate FreeAgent Desktop. [CF] smartd: Fix directive '-l selftest' (ticket #36) diff --git a/smartmontools/NEWS b/smartmontools/NEWS index baff2562472998c6f6438e99c4cd2dc1a97335e3..b1cb9da211ed774708849f7475aafc529684b4c3 100644 --- a/smartmontools/NEWS +++ b/smartmontools/NEWS @@ -14,6 +14,7 @@ Summary: smartmontools release 5.40 which can be downloaded from SVN. - Fix regression in smartctl option '-q, --quietmode'. - Fix regression in smartd directive '-l selftest'. +- Linux: Allow smartd 'DEVICESCAN -d sat'. Date 2009-12-09 Summary: smartmontools release 5.39 (UNSTABLE/EXPERIMENTAL) diff --git a/smartmontools/os_linux.cpp b/smartmontools/os_linux.cpp index bcd5e2a560509937716dc59253c24e78c173245f..96d7d938385296db08a226bc66d2c1183f5d664a 100644 --- a/smartmontools/os_linux.cpp +++ b/smartmontools/os_linux.cpp @@ -831,17 +831,22 @@ class linux_scsi_device public /*extends*/ linux_smart_device { public: - linux_scsi_device(smart_interface * intf, const char * dev_name, const char * req_type); + linux_scsi_device(smart_interface * intf, const char * dev_name, + const char * req_type, bool scanning = false); virtual smart_device * autodetect_open(); virtual bool scsi_pass_through(scsi_cmnd_io * iop); + +private: + bool m_scanning; ///< true if created within scan_smart_devices }; linux_scsi_device::linux_scsi_device(smart_interface * intf, - const char * dev_name, const char * req_type) + const char * dev_name, const char * req_type, bool scanning /*= false*/) : smart_device(intf, dev_name, "scsi", req_type), - linux_smart_device(O_RDWR | O_NONBLOCK, O_RDONLY | O_NONBLOCK) + linux_smart_device(O_RDWR | O_NONBLOCK, O_RDONLY | O_NONBLOCK), + m_scanning(scanning) { } @@ -2646,8 +2651,13 @@ smart_device * linux_scsi_device::autodetect_open() return this; // No Autodetection if device type was specified by user - if (*get_req_type()) - return this; + bool sat_only = false; + if (*get_req_type()) { + // Detect SAT if device object was created by scan_smart_devices(). + if (!(m_scanning && !strcmp(get_req_type(), "sat"))) + return this; + sat_only = true; + } // The code below is based on smartd.cpp:SCSIFilterKnown() @@ -2668,36 +2678,43 @@ smart_device * linux_scsi_device::autodetect_open() int avail_len = req_buff[4] + 5; int len = (avail_len < req_len ? avail_len : req_len); - if (len < 36) + if (len < 36) { + if (sat_only) { + close(); + set_err(EIO, "INQUIRY too short for SAT"); + } return this; + } // Use INQUIRY to detect type + if (!sat_only) { - // 3ware ? - if (!memcmp(req_buff + 8, "3ware", 5) || !memcmp(req_buff + 8, "AMCC", 4)) { - close(); - set_err(EINVAL, "AMCC/3ware controller, please try adding '-d 3ware,N',\n" - "you may need to replace %s with /dev/twaN or /dev/tweN", get_dev_name()); - return this; - } + // 3ware ? + if (!memcmp(req_buff + 8, "3ware", 5) || !memcmp(req_buff + 8, "AMCC", 4)) { + close(); + set_err(EINVAL, "AMCC/3ware controller, please try adding '-d 3ware,N',\n" + "you may need to replace %s with /dev/twaN or /dev/tweN", get_dev_name()); + return this; + } - // DELL? - if (!memcmp(req_buff + 8, "DELL PERC", 12) || !memcmp(req_buff + 8, "MegaRAID", 8)) { - close(); - set_err(EINVAL, "DELL or MegaRaid controller, please try adding '-d megaraid,N'"); - return this; - } + // DELL? + if (!memcmp(req_buff + 8, "DELL PERC", 12) || !memcmp(req_buff + 8, "MegaRAID", 8)) { + close(); + set_err(EINVAL, "DELL or MegaRaid controller, please try adding '-d megaraid,N'"); + return this; + } - // Marvell ? - if (len >= 42 && !memcmp(req_buff + 36, "MVSATA", 6)) { - //pout("Device %s: using '-d marvell' for ATA disk with Marvell driver\n", get_dev_name()); - close(); - smart_device_auto_ptr newdev( - new linux_marvell_device(smi(), get_dev_name(), get_req_type()) - ); - newdev->open(); // TODO: Can possibly pass open fd - delete this; - return newdev.release(); + // Marvell ? + if (len >= 42 && !memcmp(req_buff + 36, "MVSATA", 6)) { + //pout("Device %s: using '-d marvell' for ATA disk with Marvell driver\n", get_dev_name()); + close(); + smart_device_auto_ptr newdev( + new linux_marvell_device(smi(), get_dev_name(), get_req_type()) + ); + newdev->open(); // TODO: Can possibly pass open fd + delete this; + return newdev.release(); + } } // SAT or USB ? @@ -2709,6 +2726,11 @@ smart_device * linux_scsi_device::autodetect_open() } // Nothing special found + + if (sat_only) { + close(); + set_err(EIO, "Not a SAT device"); + } return this; } @@ -2891,7 +2913,7 @@ bool linux_smart_interface::get_dev_list(smart_device_list & devlist, if (autodetect) dev = autodetect_smart_device(name); else if (is_scsi) - dev = new linux_scsi_device(this, name, req_type); + dev = new linux_scsi_device(this, name, req_type, true /*scanning*/); else dev = new linux_ata_device(this, name, req_type); if (dev) // autodetect_smart_device() may return nullptr. @@ -2917,7 +2939,8 @@ bool linux_smart_interface::scan_smart_devices(smart_device_list & devlist, type = ""; bool scan_ata = (!*type || !strcmp(type, "ata" )); - bool scan_scsi = (!*type || !strcmp(type, "scsi")); + // "sat" detection will be later handled in linux_scsi_device::autodetect_open() + bool scan_scsi = (!*type || !strcmp(type, "scsi") || !strcmp(type, "sat")); if (!(scan_ata || scan_scsi)) return true;