Don't add sd* device if it's 3ware controller.

Properly add devices detected through 3ware scan (linux).
Limit smartctl sequential scans to 24 drives (it takes too long without it).
This commit is contained in:
Alexander Shaduri
2011-04-19 17:59:44 +00:00
parent 8ae3c42100
commit 213c26db3f
4 changed files with 31 additions and 18 deletions
+10 -6
View File
@@ -43,13 +43,17 @@ Set tooltips wherever we have "No description available".
!!! Allow quitting when test is running (ask first).
+"Add Device" window needs tooltips on both labels and entries.
+ Don't mention -d 3ware on windows in the tooltip.
+ Both points go for the preferences window as well.
Display -d type in the main window, tooltip, drive info window.
Otherwise it's just /dev/twa0.
+Fixed usb drive re-detection with scsi.
+Fixed invalid regexps in tw_cli parsing.
+Added support for "Product" field of USB drives (used instead of Device in newer smartctl)
When running smartctl on drives, run them on the driveptr-s directly,
(use -i -H -c options, maybe even drive->fetch...()), so that the drive
remembers it.
Linux: Detect scsi number for 3ware and use that for tw_cli controller.
Windows: If smartctl --scan-open returns no "sd*,port"-style devices,
check if 3dm2 is installed and execute "tw_cli show" to get the controllers.
@@ -213,7 +213,7 @@ inline std::string read_proc_scsi_scsi_file(std::vector<std::string>& lines)
/// Get number of ports using tw_cli. Return -1 on error.
inline std::string tw_cli_get_drives(const std::string& dev, int controller_no,
std::vector<StorageDeviceRefPtr> drives, ExecutorFactoryRefPtr ex_factory)
std::vector<StorageDeviceRefPtr>& drives, ExecutorFactoryRefPtr ex_factory)
{
hz::intrusive_ptr<CmdexSync> executor = ex_factory->create_executor(ExecutorFactory::ExecutorTwCli);
@@ -279,7 +279,7 @@ inline std::string tw_cli_get_drives(const std::string& dev, int controller_no,
/// Get number of ports by sequentially running smartctl on each port, until
/// one of the gives an error. Return -1 on error.
inline std::string smartctl_get_drives(const std::string& dev, const std::string& type,
int from, int to, std::vector<StorageDeviceRefPtr> drives, ExecutorFactoryRefPtr ex_factory)
int from, int to, std::vector<StorageDeviceRefPtr>& drives, ExecutorFactoryRefPtr ex_factory)
{
hz::intrusive_ptr<CmdexSync> smartctl_ex = ex_factory->create_executor(ExecutorFactory::ExecutorSmartctl);
@@ -295,7 +295,7 @@ inline std::string smartctl_get_drives(const std::string& dev, const std::string
}
if (!error_msg.empty()) {
debug_out_info("app", "Sequential port scan aborted with error: " << error_msg);
debug_out_info("app", "Smartctl returned with an error: " << error_msg);
} else {
drives.push_back(StorageDeviceRefPtr(new StorageDevice(dev, type_arg)));
}
@@ -398,8 +398,17 @@ inline std::string detect_drives_linux_proc_partitions(std::vector<StorageDevice
devices.push_back(path);
}
hz::intrusive_ptr<CmdexSync> smartctl_ex = ex_factory->create_executor(ExecutorFactory::ExecutorSmartctl);
for (std::size_t i = 0; i < devices.size(); ++i) {
drives.push_back(StorageDeviceRefPtr(new StorageDevice(devices.at(i))));
StorageDeviceRefPtr drive(new StorageDevice(devices.at(i)));
drive->fetch_basic_data_and_parse(smartctl_ex);
// 3ware controllers also export themselves as sd*. Smartctl detects that,
// so we can avoid adding them.
if (!app_pcre_match("/AMCC/3ware controller/im", drive->get_info_output())) {
drives.push_back(drive);
}
}
return std::string();
@@ -423,8 +432,10 @@ Detection:
Grep /proc/devices for "twa" or "twe" (e.g. "251 twa"). Use this for /dev/tw* part.
Grep /proc/scsi/scsi for AMCC or 3ware (LSI too?), use number of matched lines N
for /dev/tw*[0, N-1].
For detecting the number of ports, use "tw_cli /c0 show all", 0 being the controller N.
If there's no tw_cli, we'll have to scan all 128 ports.
For detecting the number of ports, use "tw_cli /cK show all", K being the controller
scsi number, which is displayed as scsiK in the scsi file.
If there's no tw_cli, we'll have to scan all the ports (up to supported maximum).
This is too slow however, so scan only 24.
Implementation notes: it seems that twe uses "3ware" and twa uses "AMCC".
We can't handle a situation with both twa and twe present, since we don't know
@@ -485,7 +496,8 @@ inline std::string detect_drives_linux_3ware(std::vector<StorageDeviceRefPtr>& d
error_msg = tw_cli_get_drives(dev, i, drives, ex_factory);
if (!error_msg.empty()) { // no tw_cli
error_msg = smartctl_get_drives(dev, "3ware,%d", 0, (twa_found ? 127 : 15), drives, ex_factory);
// 128 smartctl calls are too much (it's too slow). Settle for 24.
error_msg = smartctl_get_drives(dev, "3ware,%d", 0, (twa_found ? 24 : 15), drives, ex_factory);
}
if (!error_msg.empty()) {
+1 -4
View File
@@ -153,11 +153,10 @@ std::string StorageDevice::fetch_basic_data_and_parse(hz::intrusive_ptr<CmdexSyn
this->clear_fetched(); // clear everything fetched before, including outputs
std::string output;
// We don't use "--all" - it may cause really screwed up the output (tests, etc...).
// This looks just like "--info" only on non-smart devices.
// --info --health --capabilities
std::string error_msg = execute_device_smartctl("-i -H -c", smartctl_ex, output, true); // set type to invalid if needed
std::string error_msg = execute_device_smartctl("-i -H -c", smartctl_ex, this->info_output_, true); // set type to invalid if needed
// Smartctl 5.39 cvs/svn version defaults to usb type on at least linux and windows.
// This means that the old SCSI identify command isn't executed by default,
@@ -174,8 +173,6 @@ std::string StorageDevice::fetch_basic_data_and_parse(hz::intrusive_ptr<CmdexSyn
if (!error_msg.empty())
return error_msg;
this->info_output_ = output;
// Set some properties too - they are needed for e.g. AODC status, etc...
return this->parse_basic_data(true);
}
+1 -1
View File
@@ -68,7 +68,7 @@ class StorageDevice : public hz::intrusive_ptr_referenced {
// clear everything fetched before.
void clear_fetched(bool including_outputs = true);
/// Calls "smartctl --info" (info section), then parse_basic_data().
/// Calls "smartctl -i -H -c" (info section, health, capabilities), then parse_basic_data().
/// Called during drive detection.
/// Note: this will clear the non-basic properties!
std::string fetch_basic_data_and_parse(hz::intrusive_ptr<CmdexSync> smartctl_ex = 0);