diff --git a/CHANGES.txt b/CHANGES.txt
index 90e3780..856c7f0 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,3 +1,8 @@
+v3.5.96
+- Added option to set write_mostly for your internal HDDs so DSM will normally read from your faster internal SSD(s).
+ - It can automatically set DSM to read from your internal SSDs.
+ - Or you can tell the script which internal drive(s) DSM should read from.
+
v3.5.94
- Updated to support newer drive db versions.
- Synology added size_gb in a recent host v7 version (in SynoOfflinePack 764).
diff --git a/README.md b/README.md
index 4a6b63c..7270654 100644
--- a/README.md
+++ b/README.md
@@ -30,6 +30,9 @@ #### What the script does:
* Optionally disable DSM's "support_memory_compatibility" to prevent non-Synology memory notifications.
* Optionally edits max supported memory to match the amount of memory installed, if installed memory is greater than the current max memory setting.
* DSM only uses the max memory setting when calculating the reserved RAM area size for SSD caches.
+* Optionally set write_mostly for your internal HDDs so DSM will normally read from your faster internal SSD(s).
+ * It can automatically set DSM to read from your internal SSDs.
+ * Or you can tell the script which internal drive(s) DSM should read from.
* Optionally disables Western Digital Device Analytics (aka WDDA) to prevent DSM showing a [warning for WD drives that are 3 years old](https://arstechnica.com/gadgets/2023/06/clearly-predatory-western-digital-sparks-panic-anger-for-age-shaming-hdds).
* DSM 7.2.1 already has WDDA disabled.
* Enables M2D20, M2D18, M2D17 and E10M20-T1 if present on Synology NAS that don't officially support them.
@@ -81,7 +84,16 @@ ### Options when running the script
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 slow internal drives so DSM
+ runs from the fast internal drive(s).
+ -S automatically sets internal SSDs as DSM default
+ --ssd=DRIVE requires the fast drive(s) as argument,
+ or restore as the argument to set drives to default
+ --ssd=sata1 or --ssd=sata1,sata2 or --ssd=sda etc
+ --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)
--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
diff --git a/syno_hdd_db.sh b/syno_hdd_db.sh
index 6840261..beb944d 100644
--- a/syno_hdd_db.sh
+++ b/syno_hdd_db.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.96"
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,15 @@ 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 slow internal drives so DSM
+ runs from the fast internal drive(s).
+ -S automatically sets internal SSDs as DSM default
+ --ssd=DRIVE requires the fast drive(s) as argument,
+ or restore as the argument to set drives to default
+ --ssd=sata1 or --ssd=sata1,sata2 or --ssd=sda etc
+ --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 +108,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 +121,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 +363,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 +760,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 +769,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 +777,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 +1111,7 @@ else
echo
fi
+
#------------------------------------------------------------------------------
# Check databases and add our drives if needed
@@ -1123,10 +1150,10 @@ 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
else
@@ -1242,7 +1269,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 +1291,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 +1310,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 +1429,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 +1635,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 +1690,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 +1948,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 +1980,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[em]"; then
if [[ $m2 != "no" ]]; then
if [[ $m2exists == "yes" ]]; then
# Check if m2 volume support is enabled
@@ -1971,7 +2083,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 +2106,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!"
@@ -2052,3 +2164,4 @@ if [[ $dsm -eq "6" ]] || [[ $rebootmsg == "yes" ]]; then
fi
exit
+