diff --git a/hdddb/all/usr/bin/hdddb.sh b/hdddb/all/usr/bin/hdddb.sh index 6840261..09db7bb 100755 --- a/hdddb/all/usr/bin/hdddb.sh +++ b/hdddb/all/usr/bin/hdddb.sh @@ -17,6 +17,10 @@ # https://smarthdd.com/database/ # RECENT CHANGES +# Make DSM read md0 and md1 from SSD drive(s) if internal SSD and HDD are installed. +# https://github.com/007revad/Synology_HDD_db/issues/318 +# https://www.techspark.de/speed-up-synology-dsm-with-hdd-ssd/ +# https://raid.wiki.kernel.org/index.php/Write-mostly # TODO # Enable SMART Attributes button on Storage Manager @@ -25,7 +29,7 @@ # /var/packages/StorageManager/target/ui/storage_panel.js -scriptver="v3.5.94" +scriptver="v3.5.97" script=Synology_HDD_db repo="007revad/Synology_HDD_db" scriptname=syno_hdd_db @@ -38,7 +42,7 @@ if [ ! "$(basename "$BASH")" = bash ]; then fi # Check script is running on a Synology NAS -if ! /usr/bin/uname -a | grep -i synology >/dev/null; then +if ! /usr/bin/uname -a | grep -q -i synology; then echo "This script is NOT running on a Synology NAS!" echo "Copy the script to a folder on the Synology" echo "and run it from there." @@ -69,7 +73,14 @@ Options: DSM 7.2.1 already has WDDA disabled -p, --pcie Enable creating volumes on M2 in unknown PCIe adaptor -e, --email Disable colored text in output scheduler emails - --restore Undo all changes made by the script + -S, --ssd=DRIVE Enable write_mostly on internal HDDs so DSM primary + reads from internal SSDs or your specified drives + -S automatically sets internal SSDs as DSM preferred + --ssd=DRIVE requires the fast drive(s) as argument, + or restore as the argument to reset drives to default + --ssd=sata1 or --ssd=sata1,sata2 or --ssd=sda etc + --ssd=restore + --restore Undo all changes made by the script (except -S --ssd) --autoupdate=AGE Auto update script (useful when script is scheduled) AGE is how many days old a release must be before auto-updating. AGE must be a number: 0 or greater @@ -96,12 +107,12 @@ args=("$@") # Check for flags with getopt -if options="$(getopt -o abcdefghijklmnopqrstuvwxyz0123456789 -l \ - restore,showedits,noupdate,nodbupdate,m2,force,incompatible,ram,pcie,wdda,email,autoupdate:,help,version,debug \ +if options="$(getopt -o Sabcdefghijklmnopqrstuvwxyz0123456789 -l \ + ssd:,restore,showedits,noupdate,nodbupdate,m2,force,incompatible,ram,pcie,wdda,email,autoupdate:,help,version,debug \ -- "$@")"; then eval set -- "$options" while true; do - case "${1,,}" in + case "$1" in --restore) # Restore changes from backups restore=yes break @@ -109,6 +120,20 @@ if options="$(getopt -o abcdefghijklmnopqrstuvwxyz0123456789 -l \ -s|--showedits) # Show edits done to host db file showedits=yes ;; + -S) # Enable writemostly for md0 and md1 + ssd=yes + ;; + --ssd) # Enable writemostly for md0 and md1 + ssd=yes + if [[ ${2,,} == "restore" ]]; then + ssd_restore=yes + else + IFS=$',' + for d in $2; do ssds_writemostly+=("${d,,}"); done + unset IFS + fi + shift + ;; -n|--nodbupdate|--noupdate) # Disable disk compatibility db updates nodbupdate=yes ;; @@ -337,7 +362,7 @@ scriptvol=$(echo "$scriptpath" | cut -d"/" -f2) vg=$(lvdisplay | grep /volume_"${scriptvol#volume}" | cut -d"/" -f3) md=$(pvdisplay | grep -B 1 -E '[ ]'"$vg" | grep /dev/ | cut -d"/" -f3) # shellcheck disable=SC2002 # Don't warn about "Useless cat" -if cat /proc/mdstat | grep "$md" | grep nvme >/dev/null; then +if cat /proc/mdstat | grep "$md" | grep -q nvme; then echo -e "\n${Yellow}WARNING${Off} Don't store this script on an NVMe volume!" fi @@ -734,7 +759,7 @@ set_vendor(){ if [[ $vendor ]]; then # DS1817+, DS1517+, RS1219+, RS818+ don't have pci_vendor_ids.conf if [[ "$vidfile" ]]; then - if ! grep "$vid" "$vidfile" >/dev/null; then + if ! grep -q "$vid" "$vidfile"; then /usr/syno/bin/synosetkeyvalue "$vidfile" "${vid,,}" "$vendor" val=$(/usr/syno/bin/synogetkeyvalue "$vidfile" "${vid,,}") if [[ $val == "${vendor}" ]]; then @@ -743,7 +768,7 @@ set_vendor(){ echo -e "\nFailed to add $vendor to pci_vendor_ids!" >&2 fi fi - if ! grep "$vid" "$vidfile2" >/dev/null; then + if ! grep -q "$vid" "$vidfile2"; then /usr/syno/bin/synosetkeyvalue "$vidfile2" "${vid,,}" "$vendor" fi @@ -751,10 +776,10 @@ set_vendor(){ if [[ ${#vid} -eq "5" ]]; then vid="0x0${vid: -3}" fi - if ! grep "$vid" "$vidfile" >/dev/null; then + if ! grep -q "$vid" "$vidfile"; then /usr/syno/bin/synosetkeyvalue "$vidfile" "${vid,,}" "$vendor" fi - if ! grep "$vid" "$vidfile2" >/dev/null; then + if ! grep -q "$vid" "$vidfile2"; then /usr/syno/bin/synosetkeyvalue "$vidfile2" "${vid,,}" "$vendor" fi @@ -1085,6 +1110,7 @@ else echo fi + #------------------------------------------------------------------------------ # Check databases and add our drives if needed @@ -1123,14 +1149,20 @@ fi getdbtype(){ # Detect drive db type # Synology misspelt compatibility as compatbility - if grep -F '{"disk_compatbility_info":' "$1" >/dev/null; then + if grep -q -F '{"disk_compatbility_info":' "$1"; then # DSM 7 drive db files start with {"disk_compatbility_info": dbtype=7 - elif grep -F '{"success":1,"list":[' "$1" >/dev/null; then + elif grep -q -F '{"success":1,"list":[' "$1"; then # DSM 6 drive db files start with {"success":1,"list":[ dbtype=6 + elif [[ ! $1 =~ .*'.db.new' ]]; then + if [[ $(stat -c%s "$1") -eq "0" ]]; then + echo -e "${Error}ERROR${Off} $(basename -- "${1}") is 0 bytes!" >&2 + else + echo -e "${Error}ERROR${Off} Unknown database type $(basename -- "${1}")!" >&2 + fi + dbtype=1 else - echo -e "${Error}ERROR${Off} Unknown database type $(basename -- "${1}")!" >&2 dbtype=1 fi #echo "db type: $dbtype" >&2 # debug @@ -1242,7 +1274,7 @@ updatedb(){ if [[ $dbtype -gt "6" ]]; then # db type 7 used from DSM 7.1 and later - if grep "$hdmodel"'":{"'"$fwrev" "$2" >/dev/null; then + if grep -q "$hdmodel"'":{"'"$fwrev" "$2"; then echo -e "${Yellow}$hdmodel${Off} already exists in ${Cyan}$(basename -- "$2")${Off}" >&2 else common_string=\"size_gb\":$size_gb, @@ -1264,13 +1296,13 @@ updatedb(){ default="$default"}]}}} # Synology misspelt compatibility as compatbility - if grep '"disk_compatbility_info":{}' "$2" >/dev/null; then + if grep -q '"disk_compatbility_info":{}' "$2"; then # Replace "disk_compatbility_info":{} with # "disk_compatbility_info":{"WD40PURX-64GVNY0":{"80.00A80":{ ... }}},"default":{ ... }}}} #echo "Edit empty db file:" # debug editdb7 "empty" "$2" - elif grep '"'"$hdmodel"'":' "$2" >/dev/null; then + elif grep -q '"'"$hdmodel"'":' "$2"; then # Replace "WD40PURX-64GVNY0":{ with "WD40PURX-64GVNY0":{"80.00A80":{ ... }}}, #echo "Insert firmware version:" # debug editdb7 "insert" "$2" @@ -1283,25 +1315,25 @@ updatedb(){ fi # Edit existing drives in db with compatibility:unverified # Issue #224 - if grep 'unverified' "$2" >/dev/null; then + if grep -q 'unverified' "$2"; then sed -i 's/unverified/support/g' "$2" - if ! grep 'unverified' "$2" >/dev/null; then + if ! grep -q 'unverified' "$2"; then echo -e "Edited unverified drives in ${Cyan}$(basename -- "$2")${Off}" >&2 fi fi # Edit existing drives in db with compatibility:not_support if [[ $incompatible == "yes" ]]; then - if grep 'not_support' "$2" >/dev/null; then + if grep -q 'not_support' "$2"; then sed -i 's/not_support/support/g' "$2" - if ! grep 'not_support' "$2" >/dev/null; then + if ! grep -q 'not_support' "$2"; then echo -e "Edited incompatible drives in ${Cyan}$(basename -- "$2")${Off}" >&2 fi fi fi elif [[ $dbtype -eq "6" ]]; then # db type 6 used up to DSM 7.0.1 - if grep "$hdmodel" "$2" >/dev/null; then + if grep -q "$hdmodel" "$2"; then echo -e "${Yellow}$hdmodel${Off} already exists in ${Cyan}$(basename -- "$2")${Off}" >&2 else # example: @@ -1402,7 +1434,7 @@ enable_card(){ backupdb "$adapter_cards2" long # Check if section exists - if ! grep '^\['"$2"'\]$' "$1" >/dev/null; then + if ! grep -q '^\['"$2"'\]$' "$1"; then echo -e "Section [$2] not found in $(basename -- "$1")!" >&2 return fi @@ -1608,7 +1640,7 @@ edit_modeldtb(){ # Edit model.dts for c in "${cards[@]}"; do # Edit model.dts if needed - if ! grep "$c" "$dtb_file" >/dev/null; then + if ! grep -q "$c" "$dtb_file"; then dts_m2_card "$c" "$dts_file" echo -e "Added ${Yellow}$c${Off} to ${Cyan}model${hwrev}.dtb${Off}" >&2 else @@ -1663,6 +1695,91 @@ for c in "${m2cards[@]}"; do done +#------------------------------------------------------------------------------ +# Set or restore writemostly + +set_writemostly(){ + # $1 is writemostly or in_sync + # $2 is sata1 or sas1 or sda etc + if [[ ${1::2} == "sd" ]]; then + # sda etc + # md0 DSM system partition + echo "$1" > /sys/block/md0/md/dev-"${2}"1/state + # Show setting + echo -n "$2 DSM partition: " + cat /sys/block/md0/md/dev-"${2}"1/state + + # md1 DSM swap partition + echo "$1" > /sys/block/md1/md/dev-"${2}"2/state + # Show setting + echo -n "$2 Swap partition: " + cat /sys/block/md1/md/dev-"${2}"2/state + else + # sata1 or sas1 etc + # md0 DSM system partition + echo "$1" > /sys/block/md0/md/dev-"${2}"p1/state + # Show setting + echo -n "$2 DSM partition: " + cat /sys/block/md0/md/dev-"${2}"p1/state + + # md1 DSM swap partition + echo "$1" > /sys/block/md1/md/dev-"${2}"p2/state + # Show setting + echo -n "$2 Swap partition: " + cat /sys/block/md1/md/dev-"${2}"p2/state + fi +} + +if [[ $ssd == "yes" ]]; then + # Get array of internal drives + readarray -t internal_drives < <(synodisk --enum -t internal | grep 'Disk path' | cut -d"/" -f3) + + if [[ $ssd_restore == "yes" ]]; then + # Restore all internal drives to just in_sync + echo -e "\nRestoring internal drive's state:" + for idrive in "${internal_drives[@]}"; do + #if ! grep -q "write_mostly"; then + set_writemostly -writemostly "$idrive" + #fi + done + + elif [[ ${#ssds_writemostly[@]} -gt "0" ]]; then + # User specified their fast drive(s) + echo -e "\nSetting slow internal HDDs state to write_mostly:" + for idrive in "${internal_drives[@]}"; do + if [[ ! ${ssds_writemostly[*]} =~ $idrive ]]; then + set_writemostly writemostly "$idrive" + fi + done + + else + # Get list of internal HDDs and qty of SSDs + internal_ssd_qty="0" + for idrive in "${internal_drives[@]}"; do + internal_drive="$(echo "$idrive" | awk '{printf $4}')" + if synodisk --isssd "$internal_drive" >/dev/null; then + # exit code 0 = is not SSD + # exit code 1 = is SSD + + # Add internal HDDs to array + internal_hdds+=("$internal_drive") + else + # Count number of internal 2.5 inch SSDs + internal_ssd_qty=$((internal_ssd_qty +1)) + fi + done + + # Set HDDs to writemostly if there's also internal SSDs + if [[ $internal_ssd_qty -gt "0" ]] && [[ ${#internal_hdds[@]} -gt "0" ]]; then + # There are internal SSDs and HDDs + echo -e "\nSetting internal HDDs state to write_mostly:" + for idrive in "${internal_hdds[@]}"; do + set_writemostly writemostly "$idrive" + done + fi + fi +fi + #------------------------------------------------------------------------------ # Edit /etc.defaults/synoinfo.conf @@ -1836,7 +1953,7 @@ fi # Enable nvme support # shellcheck disable=SC2010 # Don't warn about "Don't use ls | grep" -if ls /dev | grep nvme >/dev/null ; then +if ls /dev | grep -q nvme; then if [[ $m2 != "no" ]]; then # Check if nvme support is enabled setting="$(/usr/syno/bin/synogetkeyvalue $synoinfo supportnvme)" @@ -1868,7 +1985,7 @@ fi # Enable m2 volume support # shellcheck disable=SC2010 # Don't warn about "Don't use ls | grep" -if ls /dev | grep "nv[em]" >/dev/null ; then +if ls /dev | grep -q "nv[cm]"; then if [[ $m2 != "no" ]]; then if [[ $m2exists == "yes" ]]; then # Check if m2 volume support is enabled @@ -1971,7 +2088,7 @@ if [[ -f "$strgmgr" ]] && [[ $buildnumber -gt 42962 ]]; then # DSM 7.2 and later if [[ ${#m2cards[@]} -gt "0" ]] || [[ $forcepci == "yes" ]]; then - if grep 'notSupportM2Pool_addOnCard' "$strgmgr" >/dev/null; then + if grep -q 'notSupportM2Pool_addOnCard' "$strgmgr"; then # Backup storage_panel.js" if [[ $buildnumber -gt 64570 ]]; then @@ -1994,7 +2111,7 @@ if [[ -f "$strgmgr" ]] && [[ $buildnumber -gt 42962 ]]; then sed -i 's/notSupportM2Pool_addOnCard:this.T("disk_info","disk_reason_m2_add_on_card"),//g' "$strgmgr" sed -i 's/},{isConditionInvalid:0/dev/null; then + if ! grep -q 'notSupportM2Pool_addOnCard' "$strgmgr"; then echo -e "Enabled creating pool on drives in M.2 adaptor card." else echo -e "${Error}ERROR${Off} Failed to enable creating pool on drives in M.2 adaptor card!"