During cooldown keep spinning down any disk that is spun up

This commit is contained in:
Andrea Mazzoleni 2025-10-26 11:24:14 +01:00
parent b549bffd4c
commit ac986579d7
5 changed files with 97 additions and 2 deletions

View file

@ -973,6 +973,7 @@ void state_device(struct snapraid_state* state, int operation, tommy_list* filte
case DEVICE_LIST : ope = "Device listing"; break;
case DEVICE_SMART : ope = "Smart"; break;
case DEVICE_PROBE : ope = "Probe"; break;
case DEVICE_DOWNIFUP : ope = "Spindown"; break;
}
log_fatal("%s is unsupported in this platform.\n", ope);
} else {

View file

@ -2747,6 +2747,22 @@ retry:
return 0;
}
/**
* Spin down a specific device if it's up
*/
static int devdownifup(uint64_t device, const char* name, const char* smartctl, int* power)
{
*power = POWER_UNKNOWN;
if (devprobe(device, name, smartctl, power) != 0)
return -1;
if (*power == POWER_ACTIVE)
return devdown(device, name, smartctl);
return 0;
}
/**
* Spin up a device.
*/
@ -2845,6 +2861,29 @@ static void* thread_spindown(void* arg)
return 0;
}
/**
* Thread for spinning down.
*/
static void* thread_spindownifup(void* arg)
{
devinfo_t* devinfo = arg;
uint64_t start;
int power;
start = tick_ms();
if (devdownifup(devinfo->device, devinfo->name, devinfo->smartctl, &power) != 0) {
/* LCOV_EXCL_START */
return (void*)-1;
/* LCOV_EXCL_STOP */
}
if (power == POWER_ACTIVE)
msg_status("Spundown device '%s' for disk '%s' in %" PRIu64 " ms.\n", devinfo->file, devinfo->name, tick_ms() - start);
return 0;
}
/**
* Thread for getting smart info.
*/
@ -2949,6 +2988,7 @@ int devquery(tommy_list* high, tommy_list* low, int operation, int others)
case DEVICE_DOWN : func = thread_spindown; break;
case DEVICE_SMART : func = thread_smart; break;
case DEVICE_PROBE : func = thread_probe; break;
case DEVICE_DOWNIFUP : func = thread_spindownifup; break;
}
if (!func)

View file

@ -523,6 +523,7 @@ typedef struct devinfo_struct devinfo_t;
#define DEVICE_UP 2
#define DEVICE_SMART 3
#define DEVICE_PROBE 4
#define DEVICE_DOWNIFUP 5
/**
* Query all the "high" level devices with the specified operation,

View file

@ -301,7 +301,7 @@ int state_thermal_alarm(struct snapraid_state* state)
void state_thermal_cooldown(struct snapraid_state* state)
{
unsigned sleep_time = state->thermal_cooldown_time;
int sleep_time = state->thermal_cooldown_time;
if (sleep_time == 0)
sleep_time = 5 * 60; /* default sleep time */
@ -321,7 +321,13 @@ void state_thermal_cooldown(struct snapraid_state* state)
log_flush();
sleep(sleep_time);
/* every 30 seconds spin down any disk that was spunup */
while (sleep_time > 0) {
state_device(state, DEVICE_DOWNIFUP, 0);
sleep(30);
sleep_time -= 30;
}
if (!global_interrupt) { /* don't wake-up if we are interrupting */
log_tag("thermal:spinup\n");

View file

@ -1350,6 +1350,24 @@ static int devdown(dev_t device, const char* name, const char* smartctl)
}
#endif
/**
* Spin down a specific device if it's up.
*/
#if HAVE_LINUX_DEVICE
static int devdownifup(dev_t device, const char* name, const char* smartctl, int* power)
{
*power = POWER_UNKNOWN;
if (devprobe(device, name, smartctl, power) != 0)
return -1;
if (*power == POWER_ACTIVE)
return devdown(device, name, smartctl);
return 0;
}
#endif
/**
* Spin up a specific device.
*/
@ -1465,6 +1483,34 @@ static void* thread_spindown(void* arg)
#endif
}
/**
* Thread for spinning down.
*/
static void* thread_spindownifup(void* arg)
{
#if HAVE_LINUX_DEVICE
devinfo_t* devinfo = arg;
uint64_t start;
int power;
start = tick_ms();
if (devdownifup(devinfo->device, devinfo->name, devinfo->smartctl, &power) != 0) {
/* LCOV_EXCL_START */
return (void*)-1;
/* LCOV_EXCL_STOP */
}
if (power == POWER_ACTIVE)
msg_status("Spundown device '%s' for disk '%s' in %" PRIu64 " ms.\n", devinfo->file, devinfo->name, tick_ms() - start);
return 0;
#else
(void)arg;
return (void*)-1;
#endif
}
/**
* Thread for getting smart info.
*/
@ -1620,6 +1666,7 @@ int devquery(tommy_list* high, tommy_list* low, int operation, int others)
case DEVICE_DOWN : func = thread_spindown; break;
case DEVICE_SMART : func = thread_smart; break;
case DEVICE_PROBE : func = thread_probe; break;
case DEVICE_DOWNIFUP : func = thread_spindownifup; break;
}
if (!func)