| 615 | } |
| 616 | |
| 617 | static int block_device_run_smartctl(const string& devname, int timeout, |
| 618 | std::string *result) |
| 619 | { |
| 620 | string device = "/dev/" + devname; |
| 621 | |
| 622 | // when using --json, smartctl will report its errors in JSON format to stdout |
| 623 | SubProcessTimed smartctl( |
| 624 | "sudo", SubProcess::CLOSE, SubProcess::PIPE, SubProcess::CLOSE, |
| 625 | timeout); |
| 626 | smartctl.add_cmd_args( |
| 627 | "smartctl", |
| 628 | //"-a", // all SMART info |
| 629 | "-x", // all SMART and non-SMART info |
| 630 | "--json=o", |
| 631 | device.c_str(), |
| 632 | NULL); |
| 633 | |
| 634 | int ret = smartctl.spawn(); |
| 635 | if (ret != 0) { |
| 636 | *result = std::string("error spawning smartctl: ") + smartctl.err(); |
| 637 | return ret; |
| 638 | } |
| 639 | |
| 640 | bufferlist output; |
| 641 | ret = output.read_fd(smartctl.get_stdout(), 100*1024); |
| 642 | if (ret < 0) { |
| 643 | *result = std::string("failed read smartctl output: ") + cpp_strerror(-ret); |
| 644 | } else { |
| 645 | ret = 0; |
| 646 | *result = output.to_str(); |
| 647 | } |
| 648 | |
| 649 | int joinerr = smartctl.join(); |
| 650 | // Bit 0: Command line did not parse. |
| 651 | // Bit 1: Device open failed, device did not return an IDENTIFY DEVICE structure, or device is in a low-power mode (see '-n' option above). |
| 652 | // Bit 2: Some SMART or other ATA command to the disk failed, or there was a checksum error in a SMART data structure (see '-b' option above). |
| 653 | // Bit 3: SMART status check returned "DISK FAILING". |
| 654 | // Bit 4: We found prefail Attributes <= threshold. |
| 655 | // Bit 5: SMART status check returned "DISK OK" but we found that some (usage or prefail) Attributes have been <= threshold at some time in the past. |
| 656 | // Bit 6: The device error log contains records of errors. |
| 657 | // Bit 7: The device self-test log contains records of errors. [ATA only] Failed self-tests outdated by a newer successful extended self-test are ignored. |
| 658 | if (joinerr & 3) { |
| 659 | *result = "smartctl returned an error ("s + stringify(joinerr) + |
| 660 | "): stderr:\n"s + smartctl.err() + "\nstdout:\n"s + *result; |
| 661 | return -EINVAL; |
| 662 | } |
| 663 | |
| 664 | return ret; |
| 665 | } |
| 666 | |
| 667 | static std::string escape_quotes(const std::string& s) |
| 668 | { |
no test coverage detected