redhat-performance / tuned

Tuning Profile Delivery Mechanism for Linux
GNU General Public License v2.0
755 stars 171 forks source link

Unable to set APM using TuneD #560

Open moneytoo opened 8 months ago

moneytoo commented 8 months ago

Hello,

I want to enable spindown on my rarely used drive (2.5 inch Seagate BarraCuda, 5TB, model ST5000LM000). The spindown parameter works only if I modify the APM. After reconnecting power and booting, APM is at 128. Lowering APM to 127 (using hdparm -B 127) correctly applies and allows spindown.

I able to set the spindown parameter using TuneD, but not apm. This output is produced when setting a profile with APM value:

tuned.plugins.plugin_disk: Driver for device 'sda' does not support apm command

Actually, when I disable this check, APM is correctly applied.

Indeed, running hdparm -C reports the unknown state when querying it after a fresh boot. However states like standby or active are reported when using the drive.

# hdparm -C /dev/sda

/dev/sda:
 drive state is:  unknown
# hdparm -B /dev/sda

/dev/sda:
 APM_level      = 128
# hdparm -B 127 /dev/sda

/dev/sda:
 setting Advanced Power Management level to 0x7f (127)
 APM_level      = 127
# hdparm -B /dev/sda

/dev/sda:
 APM_level      = 127
# hdparm -C /dev/sda

/dev/sda:
 drive state is:  unknown
# hdparm -Y /dev/sda

/dev/sda:
 issuing sleep command
# hdparm -C /dev/sda

/dev/sda:
 drive state is:  standby
# touch /mnt/hdd/a
# hdparm -C /dev/sda

/dev/sda:
 drive state is:  active/idle

Disk details:

# hdparm -I /dev/sda

/dev/sda:

ATA device, with non-removable media
        Model Number:       ST5000LM000-2AN170
        Serial Number:      WCJ52Z2A
        Firmware Revision:  0001
        Transport:          Serial, ATA8-AST, SATA 1.0a, SATA II Extensions, SATA Rev 2.5, SATA Rev 2.6, SATA Rev 3.0
Standards:
        Used: unknown (minor revision code 0x006d)
        Supported: 10 9 8 7 6 5
        Likely used: 10
Configuration:
        Logical         max     current
        cylinders       16383   16383
        heads           16      16
        sectors/track   63      63
        --
        CHS current addressable sectors:    16514064
        LBA    user addressable sectors:   268435455
        LBA48  user addressable sectors:  9767541168
        Logical  Sector size:                   512 bytes
        Physical Sector size:                  4096 bytes
        Logical Sector-0 offset:                  0 bytes
        device size with M = 1024*1024:     4769307 MBytes
        device size with M = 1000*1000:     5000981 MBytes (5000 GB)
        cache/buffer size  = unknown
        Form Factor: 2.5 inch
        Nominal Media Rotation Rate: 5526
Capabilities:
        LBA, IORDY(can be disabled)
        Queue depth: 32
        Standby timer values: spec'd by Standard, no device specific minimum
        R/W multiple sector transfer: Max = 1   Current = ?
        Advanced power management level: 128
        Recommended acoustic management value: 208, current value: 208
        DMA: mdma0 mdma1 mdma2 udma0 udma1 udma2 udma3 udma4 udma5 *udma6
             Cycle time: min=120ns recommended=120ns
        PIO: pio0 pio1 pio2 pio3 pio4
             Cycle time: no flow control=120ns  IORDY flow control=120ns
Commands/features:
        Enabled Supported:
           *    SMART feature set
                Security Mode feature set
           *    Power Management feature set
           *    Write cache
           *    Look-ahead
           *    Host Protected Area feature set
           *    WRITE_BUFFER command
           *    READ_BUFFER command
           *    DOWNLOAD_MICROCODE
           *    Advanced Power Management feature set
                Power-Up In Standby feature set
           *    SET_FEATURES required to spinup after power up
                SET_MAX security extension
           *    48-bit Address feature set
           *    Device Configuration Overlay feature set
           *    Mandatory FLUSH_CACHE
           *    FLUSH_CACHE_EXT
           *    SMART error logging
           *    SMART self-test
           *    General Purpose Logging feature set
           *    WRITE_{DMA|MULTIPLE}_FUA_EXT
           *    64-bit World wide name
           *    WRITE_UNCORRECTABLE_EXT command
           *    {READ,WRITE}_DMA_EXT_GPL commands
           *    Segmented DOWNLOAD_MICROCODE
           *    unknown 119[6]
           *    Gen1 signaling speed (1.5Gb/s)
           *    Gen2 signaling speed (3.0Gb/s)
           *    Gen3 signaling speed (6.0Gb/s)
           *    Native Command Queueing (NCQ)
           *    Phy event counters
           *    READ_LOG_DMA_EXT equivalent to READ_LOG_EXT
           *    DMA Setup Auto-Activate optimization
                Device-initiated interface power management
           *    Software settings preservation
                unknown 78[7]
           *    SMART Command Transport (SCT) feature set
           *    SCT Write Same (AC2)
           *    SCT Data Tables (AC5)
                unknown 206[7]
                unknown 206[12] (vendor specific)
                unknown 206[13] (vendor specific)
           *    Device encrypts all user data
           *    IEEE 1667 authentication of transient storage devices
Security:
        Master password revision code = 65534
                supported
        not     enabled
        not     locked
        not     frozen
        not     expired: security count
                supported: enhanced erase
        804min for SECURITY ERASE UNIT. 2min for ENHANCED SECURITY ERASE UNIT.
Logical Unit WWN Device Identifier: 5000c500d5eedc18
        NAA             : 5
        IEEE OUI        : 000c50
        Unique ID       : 0d5eedc18
Checksum: correct

I'm using TuneD 2.20 and hdparm 9.62.

Anyway, from my naive newcomer point of view: Why is hdparm -C used to detect APM support? Why not to query APM using hdparm -B? If APM is not supported, it should produce output like this:

# hdparm -B /dev/sdb

/dev/sdb:
 APM_level      = not supported

as per hdparm source code:

if (get_apmmode) {
    get_identify_data(fd);
    if (id) {
        printf(" APM_level  = ");
        if ((id[83] & 0xc008) == 0x4008) {
            if (id[86] & 0x0008)
                printf("%u\n", id[91] & 0xff);
            else
                printf("off\n");
        } else
            printf("not supported\n");
    }
}