Отключение APM в дисках подключённых через RAID контроллер

Некоторые жёсткие диски, не только ноутбучные 2.5″ но и например 3.5″ вполне серверные модели WDC WD2002FYPS-02W3B0, имеют отвратительную особенность парковать головы. Для ноутбучных дисков это вероятно оправдано и сделано чтобы исключить повреждение дисков при возможных ударах ноутбука, компьютер то мобильный. А вот для 3.5″ дисков это сделано вроде бы как для экономии электрической энергии. Но ресурс механизма парковок ограничен и через некоторое время это приводит к его износу и поломке диска. Чтобы предотвратить износ механизма принудительной парковкой головок нужно отключить APM диска.
Отключить APM в дисках можно с помощью утилиты hdparm.

hdparm -B 255 /dev/sda

Однако она не работает если диск подключён в RAID контроллер. В этом случае RAID контроллер отдаёт в систему блочное устройство без уточнения из каких дисков оно собрано. Тоесть система обращаясь к блочному устройству представленному RAID контроллером не обращается конкретно к какому-то диску. Поэтому функционал физического доступа к порту диска через имя блочного устройства ограничен.

В этом случае нужно воспользоваться утилитой smartctl которая может добраться до дисков следующим способом:

# пример для контроллера с 7-мю дисками.
for i in `seq 0 7` ; do smartctl /dev/twa0 -d 3ware,$i --get=apm  | sed -n '/^$/,//p' | sed -e '/^[ \t]*$/d' ; done

Для отключения APM

# пример для контроллера с 7-мю дисками.
for i in `seq 0 7` ; do smartctl /dev/twa0 -d 3ware,$i --set=apm,off  | sed -n '/^$/,//p' | sed -e '/^[ \t]*$/d' ; done

В этом примере использовался контроллер 3ware с подключёнными к нему 7-мью дисками вставленными без пропусков с 0 по 7. Более универсален следующий вариант, где проверяются все контроллеры и все диски установленные в контроллерах независимо от их количества.

#!/bin/bash

# script displays APM info for all disks connected to RAID controller
# multiply controllrs are supported

  TW_CLI="/root/tw_cli/x86_64/tw_cli"

  # от номера контроллера оставить только цифру и вывести количество подключённых дисков
  TW_SHOW=`${TW_CLI} show | grep '^c[0-9][ \t]\+' | awk '{print gensub(/^c/, "", "g", $1)" "$4}'`
  #
  if [ -z "${TW_SHOW}" ] ; then
    echo -e "No controllers were found."
    exit 1
  fi

  while read TW_DEVICE TW_DISKS ; do
    if [ ${TW_DISKS} -eq 0 ] ; then
      echo "No disk present in the controller /c${TW_DEVICE}"
      continue
    fi
    while read i ; do
      echo -en "3ware /c${TW_DEVICE}/p${i} "
      smartctl /dev/twa0 -d 3ware,$i --get=apm  | sed -n '/^$/,//p' | sed -e 's/[ \t]\+/ /g;/^ *$/d'
    done < <(${TW_CLI} /c${TW_DEVICE} show phy | awk '/^phy[0-9]/{if ($4 ~ /^\/c[0-9]+\/p[0-9]+$/)print $4}' | sed -e 's|^/c[0-9]\+/p||g')
  done < <(echo -e "${TW_SHOW}")

Для отключения APM на машинах без специализированного RAID контроллера я использую скрипт который читает все блочные устройства из /proc/partitions без цифр на конце, затем проверяет включён ли там APM и если да тогда выключает его.

cat /proc/partitions | awk '{if($4 ~ /^sd[a-z]$/){print $4}}' | while read DEV ; do hdparm -B /dev/${DEV} | grep APM_level | sed -e 's/[ \t]//g' | awk -v dev=${DEV} -F= '{if ($2~/^on$/) {print dev}}' | xargs -I{} hdparm -B 255 /dev/{} >/dev/null ; done

А чтобы он запускался автоматически при каждом старте компьютера прописываю его в /etc/rc.d/rc.local
Но при замене диска без перезагрузки например в fakeraid mdraid нужно будет выполнить скрипт вручную.

Про отключение парковки головок ноутбучных дисков с поддержкой sleep, hybernate и suspend можно прочесть здесь.