projects/guix·blob master · refs

722 lines · 22.7 KiB

1;;; GNU Guix --- Functional package management for GNU
2;;; Copyright © 2017 Mathieu Othacehe <[email protected]>
3;;; Copyright © 2024 Dariqq <[email protected]>
4;;; Copyright © 2024 Ian Eure <[email protected]>
5;;; Copyright © 2025 Nigko Yerden <[email protected]>
6;;;
7;;; This file is part of GNU Guix.
8;;;
9;;; GNU Guix is free software; you can redistribute it and/or modify
10;;; it under the terms of the GNU General Public License as published by
11;;; the Free Software Foundation, either version 3 of the License, or
12;;; (at your option) any later version.
13;;;
14;;; GNU Guix is distributed in the hope that it will be useful,
15;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17;;; GNU General Public License for more details.
18;;;
19;;; You should have received a copy of the GNU General Public License
20;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
21
22(define-module (gnu services pm)
23 #:use-module (srfi srfi-1)
24 #:use-module (ice-9 match)
25 #:use-module (guix gexp)
26 #:use-module (guix packages)
27 #:use-module (guix records)
28 #:use-module (gnu packages admin)
29 #:use-module (gnu packages freedesktop)
30 #:use-module (gnu packages hardware)
31 #:use-module (gnu packages linux)
32 #:use-module (gnu services)
33 #:use-module (gnu services base)
34 #:use-module (gnu services configuration)
35 #:use-module (gnu services dbus)
36 #:use-module (gnu services shepherd)
37 #:use-module (gnu system shadow)
38 #:export (power-profiles-daemon-service-type
39 power-profiles-daemon-configuration
40
41 tlp-service-type
42 tlp-configuration
43
44 thermald-configuration
45 thermald-service-type
46
47 powertop-configuration
48 powertop-service-type
49
50 hd-idle-disk
51 hd-idle-disk?
52 hd-idle-configuration
53 hd-idle-configuration?
54 hd-idle-service-type))
55
56;;;
57;;; power-profiles-daemon
58;;;
59
60(define-configuration/no-serialization power-profiles-daemon-configuration
61 (power-profiles-daemon
62 (file-like power-profiles-daemon)
63 "The power-profiles-daemon package."))
64
65(define (power-profiles-daemon-shepherd-service config)
66 (match-record
67 config <power-profiles-daemon-configuration>
68 (power-profiles-daemon)
69 (list
70 (shepherd-service
71 (provision '(power-profiles-daemon))
72 (requirement '(user-processes dbus-system))
73 (documentation "Run the Power Profiles Daemon.")
74 (start #~(make-forkexec-constructor
75 (list #$(file-append power-profiles-daemon
76 "/libexec/power-profiles-daemon"))))
77 (stop #~(make-kill-destructor))))))
78
79(define %power-profiles-daemon-activation
80 #~(begin
81 (use-modules (guix build utils))
82 (mkdir-p "/var/lib/power-profiles-daemon")))
83
84(define power-profiles-daemon-service-type
85 (let ((config->package
86 (compose list power-profiles-daemon-configuration-power-profiles-daemon)))
87 (service-type
88 (name 'power-profiles-daemon)
89 (extensions (list
90 (service-extension shepherd-root-service-type
91 power-profiles-daemon-shepherd-service)
92 (service-extension dbus-root-service-type
93 config->package)
94 (service-extension polkit-service-type
95 config->package)
96 (service-extension profile-service-type
97 config->package)
98 (service-extension activation-service-type
99 (const %power-profiles-daemon-activation))))
100 (default-value (power-profiles-daemon-configuration))
101 (description "Run the Power Profiles Daemon"))))
102
103
104
105;;;
106;;; tlp
107;;;
108
109(define (uglify-field-name field-name)
110 (let ((str (symbol->string field-name)))
111 (string-join (string-split
112 (string-upcase
113 (if (string-suffix? "?" str)
114 (substring str 0 (1- (string-length str)))
115 str))
116 #\-)
117 "_")))
118
119(define (serialize-field field-name val)
120 (format #t "~a=~a\n" (uglify-field-name field-name) val))
121
122(define (serialize-boolean field-name val)
123 (serialize-field field-name (if val "1" "0")))
124(define-maybe boolean)
125
126(define (serialize-string field-name val)
127 (serialize-field field-name val))
128(define-maybe string)
129
130(define (space-separated-string-list? val)
131 (and (list? val)
132 (and-map (lambda (x)
133 (and (string? x) (not (string-index x #\space))))
134 val)))
135(define (serialize-space-separated-string-list field-name val)
136 (serialize-field field-name
137 (format #f "~s"
138 (string-join val " "))))
139(define-maybe space-separated-string-list)
140
141(define (non-negative-integer? val)
142 (and (exact-integer? val) (not (negative? val))))
143(define (serialize-non-negative-integer field-name val)
144 (serialize-field field-name val))
145(define-maybe non-negative-integer)
146
147(define (on-off-boolean? val)
148 (boolean? val))
149(define (serialize-on-off-boolean field-name val)
150 (serialize-field field-name (if val "on" "off")))
151(define-maybe on-off-boolean)
152
153(define (y-n-boolean? val)
154 (boolean? val))
155(define (serialize-y-n-boolean field-name val)
156 (serialize-field field-name (if val "Y" "N")))
157
158(define-configuration tlp-configuration
159 (tlp
160 (file-like tlp)
161 "The TLP package.")
162
163 (tlp-enable?
164 (boolean #t)
165 "Set to true if you wish to enable TLP.")
166
167 (tlp-default-mode
168 (string "AC")
169 "Default mode when no power supply can be detected. Alternatives are
170AC and BAT.")
171
172 (disk-idle-secs-on-ac
173 (non-negative-integer 0)
174 "Number of seconds Linux kernel has to wait after the disk goes idle,
175before syncing on AC.")
176
177 (disk-idle-secs-on-bat
178 (non-negative-integer 2)
179 "Same as @code{disk-idle-ac} but on BAT mode.")
180
181 (max-lost-work-secs-on-ac
182 (non-negative-integer 15)
183 "Dirty pages flushing periodicity, expressed in seconds.")
184
185 (max-lost-work-secs-on-bat
186 (non-negative-integer 60)
187 "Same as @code{max-lost-work-secs-on-ac} but on BAT mode.")
188
189 (cpu-scaling-governor-on-ac
190 maybe-space-separated-string-list
191 "CPU frequency scaling governor on AC mode. With intel_pstate
192driver, alternatives are powersave and performance. With acpi-cpufreq driver,
193alternatives are ondemand, powersave, performance and conservative.")
194
195 (cpu-scaling-governor-on-bat
196 maybe-space-separated-string-list
197 "Same as @code{cpu-scaling-governor-on-ac} but on BAT mode.")
198
199 (cpu-scaling-min-freq-on-ac
200 maybe-non-negative-integer
201 "Set the min available frequency for the scaling governor on AC.")
202
203 (cpu-scaling-max-freq-on-ac
204 maybe-non-negative-integer
205 "Set the max available frequency for the scaling governor on AC.")
206
207 (cpu-scaling-min-freq-on-bat
208 maybe-non-negative-integer
209 "Set the min available frequency for the scaling governor on BAT.")
210
211 (cpu-scaling-max-freq-on-bat
212 maybe-non-negative-integer
213 "Set the max available frequency for the scaling governor on BAT.")
214
215 (cpu-min-perf-on-ac
216 maybe-non-negative-integer
217 "Limit the min P-state to control the power dissipation of the CPU,
218in AC mode. Values are stated as a percentage of the available performance.")
219
220 (cpu-max-perf-on-ac
221 maybe-non-negative-integer
222 "Limit the max P-state to control the power dissipation of the CPU,
223in AC mode. Values are stated as a percentage of the available performance.")
224
225 (cpu-min-perf-on-bat
226 maybe-non-negative-integer
227 "Same as @code{cpu-min-perf-on-ac} on BAT mode.")
228
229 (cpu-max-perf-on-bat
230 maybe-non-negative-integer
231 "Same as @code{cpu-max-perf-on-ac} on BAT mode.")
232
233 (cpu-boost-on-ac?
234 maybe-boolean
235 "Enable CPU turbo boost feature on AC mode.")
236
237 (cpu-boost-on-bat?
238 maybe-boolean
239 "Same as @code{cpu-boost-on-ac?} on BAT mode.")
240
241 (sched-powersave-on-ac?
242 (boolean #f)
243 "Allow Linux kernel to minimize the number of CPU cores/hyper-threads
244used under light load conditions.")
245
246 (sched-powersave-on-bat?
247 (boolean #t)
248 "Same as @code{sched-powersave-on-ac?} but on BAT mode.")
249
250 (nmi-watchdog?
251 (boolean #f)
252 "Enable Linux kernel NMI watchdog.")
253
254 (phc-controls
255 maybe-string
256 "For Linux kernels with PHC patch applied, change CPU voltages.
257An example value would be @samp{\"F:V F:V F:V F:V\"}.")
258
259 (energy-perf-policy-on-ac
260 (string "performance")
261 "Set CPU performance versus energy saving policy on AC. Alternatives are
262performance, normal, powersave.")
263
264 (energy-perf-policy-on-bat
265 (string "powersave")
266 "Same as @code{energy-perf-policy-ac} but on BAT mode.")
267
268 (disks-devices
269 (space-separated-string-list '("sda"))
270 "Hard disk devices.")
271
272 (disk-apm-level-on-ac
273 (space-separated-string-list '("254" "254"))
274 "Hard disk advanced power management level.")
275
276 (disk-apm-level-on-bat
277 (space-separated-string-list '("128" "128"))
278 "Same as @code{disk-apm-bat} but on BAT mode.")
279
280 (disk-spindown-timeout-on-ac
281 maybe-space-separated-string-list
282 "Hard disk spin down timeout. One value has to be specified for
283each declared hard disk.")
284
285 (disk-spindown-timeout-on-bat
286 maybe-space-separated-string-list
287 "Same as @code{disk-spindown-timeout-on-ac} but on BAT mode.")
288
289 (disk-iosched
290 maybe-space-separated-string-list
291 "Select IO scheduler for disk devices. One value has to be specified
292for each declared hard disk. Example alternatives are cfq, deadline and noop.")
293
294 (sata-linkpwr-on-ac
295 (string "max_performance")
296 "SATA aggressive link power management (ALPM) level. Alternatives are
297min_power, medium_power, max_performance.")
298
299 (sata-linkpwr-on-bat
300 (string "min_power")
301 "Same as @code{sata-linkpwr-ac} but on BAT mode.")
302
303 (sata-linkpwr-blacklist
304 maybe-string
305 "Exclude specified SATA host devices for link power management.")
306
307 (ahci-runtime-pm-on-ac?
308 maybe-on-off-boolean
309 "Enable Runtime Power Management for AHCI controller and disks
310on AC mode.")
311
312 (ahci-runtime-pm-on-bat?
313 maybe-on-off-boolean
314 "Same as @code{ahci-runtime-pm-on-ac} on BAT mode.")
315
316 (ahci-runtime-pm-timeout
317 (non-negative-integer 15)
318 "Seconds of inactivity before disk is suspended.")
319
320 (pcie-aspm-on-ac
321 (string "performance")
322 "PCI Express Active State Power Management level. Alternatives are
323default, performance, powersave.")
324
325 (pcie-aspm-on-bat
326 (string "powersave")
327 "Same as @code{pcie-aspm-ac} but on BAT mode.")
328
329 (start-charge-thresh-bat0
330 maybe-non-negative-integer
331 "Percentage when battery 0 should begin charging.")
332
333 (stop-charge-thresh-bat0
334 maybe-non-negative-integer
335 "Percentage when battery 0 should stop charging.")
336
337 (start-charge-thresh-bat1
338 maybe-non-negative-integer
339 "Percentage when battery 1 should begin charging.")
340
341 (stop-charge-thresh-bat1
342 maybe-non-negative-integer
343 "Percentage when battery 1 should stop charging.")
344
345 (radeon-power-profile-on-ac
346 (string "high")
347 "Radeon graphics clock speed level. Alternatives are
348low, mid, high, auto, default.")
349
350 (radeon-power-profile-on-bat
351 (string "low")
352 "Same as @code{radeon-power-ac} but on BAT mode.")
353
354 (radeon-dpm-state-on-ac
355 (string "performance")
356 "Radeon dynamic power management method (DPM). Alternatives are
357battery, performance.")
358
359 (radeon-dpm-state-on-bat
360 (string "battery")
361 "Same as @code{radeon-dpm-state-ac} but on BAT mode.")
362
363 (radeon-dpm-perf-level-on-ac
364 (string "auto")
365 "Radeon DPM performance level. Alternatives are
366auto, low, high.")
367
368 (radeon-dpm-perf-level-on-bat
369 (string "auto")
370 "Same as @code{radeon-dpm-perf-ac} but on BAT mode.")
371
372 (wifi-pwr-on-ac?
373 (on-off-boolean #f)
374 "Wifi power saving mode.")
375
376 (wifi-pwr-on-bat?
377 (on-off-boolean #t)
378 "Same as @code{wifi-power-ac?} but on BAT mode.")
379
380 (wol-disable?
381 (y-n-boolean #t)
382 "Disable wake on LAN.")
383
384 (sound-power-save-on-ac
385 (non-negative-integer 0)
386 "Timeout duration in seconds before activating audio power saving
387 on Intel HDA and AC97 devices. A value of 0 disables power saving.")
388
389 (sound-power-save-on-bat
390 (non-negative-integer 1)
391 "Same as @code{sound-powersave-ac} but on BAT mode.")
392
393 (sound-power-save-controller?
394 (y-n-boolean #t)
395 "Disable controller in powersaving mode on Intel HDA devices.")
396
397 (bay-poweroff-on-bat?
398 (boolean #f)
399 "Enable optical drive in UltraBay/MediaBay on BAT mode.
400Drive can be powered on again by releasing (and reinserting) the eject lever
401or by pressing the disc eject button on newer models.")
402
403 (bay-device
404 (string "sr0")
405 "Name of the optical drive device to power off.")
406
407 (runtime-pm-on-ac
408 (string "on")
409 "Runtime Power Management for PCI(e) bus devices. Alternatives are
410on and auto.")
411
412 (runtime-pm-on-bat
413 (string "auto")
414 "Same as @code{runtime-pm-ac} but on BAT mode.")
415
416 (runtime-pm-all?
417 (boolean #t)
418 "Runtime Power Management for all PCI(e) bus devices, except
419blacklisted ones.")
420
421 (runtime-pm-blacklist
422 maybe-space-separated-string-list
423 "Exclude specified PCI(e) device addresses from Runtime Power Management.")
424
425 (runtime-pm-driver-blacklist
426 (space-separated-string-list '("radeon" "nouveau"))
427 "Exclude PCI(e) devices assigned to the specified drivers from
428Runtime Power Management.")
429
430 (usb-autosuspend?
431 (boolean #t)
432 "Enable USB autosuspend feature.")
433
434 (usb-blacklist
435 maybe-string
436 "Exclude specified devices from USB autosuspend.")
437
438 (usb-blacklist-wwan?
439 (boolean #t)
440 "Exclude WWAN devices from USB autosuspend.")
441
442 (usb-whitelist
443 maybe-string
444 "Include specified devices into USB autosuspend, even if they are
445already excluded by the driver or via @code{usb-blacklist-wwan?}.")
446
447 (usb-autosuspend-disable-on-shutdown?
448 maybe-boolean
449 "Enable USB autosuspend before shutdown.")
450
451 (restore-device-state-on-startup?
452 (boolean #f)
453 "Restore radio device state (bluetooth, wifi, wwan) from previous
454shutdown on system startup.")
455
456 (cpu-energy-perf-policy-on-ac
457 maybe-string
458 "Set CPU energy/performance policy when on AC mode. Possible values are
459performance, balance_performance, default, balance_power and power.")
460
461 (cpu-energy-perf-policy-on-bat
462 maybe-string
463 "Set CPU energy/performance policy when on BAT mode. Possible values are
464performance, balance_performance, default, balance_power and power."))
465
466
467(define (tlp-shepherd-service config)
468 (let* ((tlp-bin (file-append
469 (tlp-configuration-tlp config) "/sbin/tlp"))
470 (tlp-action (lambda (return-value-on-success . args)
471 #~(lambda _
472 (if (zero? (system* #$tlp-bin #$@args))
473 #$return-value-on-success
474 (not #$return-value-on-success))))))
475 (list (shepherd-service
476 (documentation "Run TLP script.")
477 (provision '(tlp))
478 (requirement '(user-processes))
479 (start (tlp-action #t "init" "start"))
480 (stop (tlp-action #f "init" "stop"))))))
481
482(define (tlp-activation config)
483 (let* ((config-str (with-output-to-string
484 (lambda ()
485 (serialize-configuration
486 config
487 tlp-configuration-fields))))
488 (config-file (plain-file "tlp" config-str)))
489 (with-imported-modules '((guix build utils))
490 #~(begin
491 (use-modules (guix build utils))
492 (copy-file #$config-file "/etc/tlp.conf")))))
493
494(define tlp-service-type
495 (service-type
496 (name 'tlp)
497 (extensions
498 (list
499 (service-extension shepherd-root-service-type
500 tlp-shepherd-service)
501 (service-extension udev-service-type
502 (compose list tlp-configuration-tlp))
503 (service-extension activation-service-type
504 tlp-activation)))
505 (default-value (tlp-configuration))
506 (description "Run TLP, a power management tool.")))
507
508(define (generate-tlp-documentation)
509 (generate-documentation
510 `((tlp-configuration ,tlp-configuration-fields))
511 'tlp-configuration))
512
513
514
515;;;
516;;; thermald
517;;;
518;;; This service implements cpu scaling. Helps prevent overheating!
519
520(define-record-type* <thermald-configuration>
521 thermald-configuration make-thermald-configuration
522 thermald-configuration?
523 (adaptive? thermald-adaptive? ;boolean
524 (default #f))
525 (ignore-cpuid-check? thermald-ignore-cpuid-check? ;boolean
526 (default #f))
527 (thermald thermald-thermald ;file-like
528 (default thermald)))
529
530(define (thermald-shepherd-service config)
531 (list
532 (shepherd-service
533 (provision '(thermald))
534 (requirement '(user-processes))
535 (documentation "Run thermald cpu frequency scaling.")
536 (start #~(make-forkexec-constructor
537 '(#$(file-append (thermald-thermald config) "/sbin/thermald")
538 "--no-daemon"
539 #$@(if (thermald-adaptive? config)
540 '("--adaptive")
541 '())
542 #$@(if (thermald-ignore-cpuid-check? config)
543 '("--ignore-cpuid-check")
544 '()))))
545 (stop #~(make-kill-destructor)))))
546
547(define thermald-service-type
548 (service-type
549 (name 'thermald)
550 (extensions (list (service-extension shepherd-root-service-type
551 thermald-shepherd-service)))
552 (default-value (thermald-configuration))
553 (description "Run thermald, a CPU frequency scaling service that helps
554prevent overheating.")))
555
556
557
558;;;
559;;; powertop
560;;;
561;;; Calls `powertop --auto-tune' to reduce energy consumption.
562
563(define-configuration powertop-configuration
564 (powertop (package powertop) "PowerTOP package to use."))
565
566(define powertop-shepherd-service
567 (match-lambda
568 (($ <powertop-configuration> powertop)
569 (shepherd-service
570 (documentation "Tune kernel power settings at boot.")
571 (provision '(powertop powertop-auto-tune))
572 (requirement '(user-processes))
573 (one-shot? #t)
574 (start #~(lambda _
575 (zero? (system* #$(file-append powertop "/sbin/powertop")
576 "--auto-tune"))))))))
577
578(define powertop-service-type
579 (service-type
580 (name 'powertop)
581 (extensions
582 (list
583 (service-extension shepherd-root-service-type
584 (compose list powertop-shepherd-service))))
585 (compose concatenate)
586 (default-value (powertop-configuration))
587 (description "Tune power-related kernel parameters to reduce energy
588 consumption.")))
589
590
591
592;;;
593;;; hd-idle
594;;;
595;;; Spins down hard disks that have been idle for a while.
596
597(define (hd-idle-command-type? val)
598 (memq val '(scsi ata)))
599(define-maybe/no-serialization hd-idle-command-type)
600
601(define (hd-idle-power-condition? val)
602 (and (exact-integer? val) (<= 0 val 15)))
603(define-maybe/no-serialization hd-idle-power-condition)
604
605(define (hd-idle-symlink-policy? val)
606 (and (exact-integer? val) (<= 0 val 1)))
607
608(define-configuration/no-serialization hd-idle-disk
609 (name
610 string
611 "The device to configure, either a name under @file{/dev} such as
612@code{\"sda\"}, or an absolute file name such as
613@code{\"/dev/disk/by-uuid/1234-5678\"}.")
614
615 (idle-time
616 maybe-non-negative-integer
617 "Number of seconds this disk must be idle before it is spun down.")
618
619 (command-type
620 maybe-hd-idle-command-type
621 "The command used to spin this disk down, either @code{'scsi} or
622@code{'ata}.")
623
624 (power-condition
625 maybe-hd-idle-power-condition
626 "The power condition to use for this disk."))
627
628(define list-of-hd-idle-disks?
629 (list-of hd-idle-disk?))
630
631(define-configuration/no-serialization hd-idle-configuration
632 (idle-time
633 (non-negative-integer 600)
634 "Number of seconds a disk must be idle before it is spun down. A value
635of @code{0} disables spinning down.")
636
637 (command-type
638 (hd-idle-command-type 'scsi)
639 "The command used to spin disks down, either @code{'scsi} or @code{'ata}.")
640
641 (power-condition
642 (hd-idle-power-condition 0)
643 "The power condition passed to the @acronym{SCSI, Small Computer System
644Interface} @code{START STOP UNIT} command, an integer between @code{0} and
645@code{15}. It is ignored when @code{command-type} is @code{'ata}.")
646
647 (symlink-policy
648 (hd-idle-symlink-policy 0)
649 "How to resolve disk names that are symbolic links. @code{0} resolves
650them once at startup, whereas with @code{1} symlinks are also resolved on
651runtime until success.")
652
653 (log-file
654 maybe-string
655 "A file name to which hd-idle logs disk spin-up and spin-down events, for
656instance @code{\"/var/log/hd-idle.log\"}.")
657
658 (ignore-spin-down-detection?
659 (boolean #f)
660 "Whether to skip detection of disks that were spun down by some other
661means.")
662
663 (debug?
664 (boolean #f)
665 "Whether to log the disk statistics that hd-idle reads on each poll.")
666
667 (disks
668 (list-of-hd-idle-disks '())
669 "A list of @code{hd-idle-disk} records describing per-disk overrides.
670Disks that are not listed here are still managed, using the values above.")
671
672 (hd-idle
673 (file-like hd-idle)
674 "The hd-idle package to use."))
675
676(define (hd-idle-disk-arguments disk)
677 (match-record disk <hd-idle-disk>
678 (name idle-time command-type power-condition)
679 `("-a" ,name
680 ,@(if (maybe-value-set? idle-time)
681 (list "-i" (number->string idle-time))
682 '())
683 ,@(if (maybe-value-set? command-type)
684 (list "-c" (symbol->string command-type))
685 '())
686 ,@(if (maybe-value-set? power-condition)
687 (list "-p" (number->string power-condition))
688 '()))))
689
690(define (hd-idle-arguments config)
691 (match-record config <hd-idle-configuration>
692 (idle-time command-type power-condition symlink-policy
693 log-file ignore-spin-down-detection? debug? disks)
694 `("-i" ,(number->string idle-time)
695 "-c" ,(symbol->string command-type)
696 "-p" ,(number->string power-condition)
697 "-s" ,(number->string symlink-policy)
698 ,@(if (maybe-value-set? log-file) (list "-l" log-file) '())
699 ,@(if ignore-spin-down-detection? '("-I") '())
700 ,@(if debug? '("-d") '())
701 ,@(append-map hd-idle-disk-arguments disks))))
702
703(define (hd-idle-shepherd-service config)
704 (list
705 (shepherd-service
706 (provision '(hd-idle))
707 (requirement '(user-processes udev))
708 (documentation "Spin down idle hard disks.")
709 (start #~(make-forkexec-constructor
710 (list #$(file-append (hd-idle-configuration-hd-idle config)
711 "/bin/hd-idle")
712 #$@(hd-idle-arguments config))))
713 (stop #~(make-kill-destructor)))))
714
715(define hd-idle-service-type
716 (service-type
717 (name 'hd-idle)
718 (extensions (list (service-extension shepherd-root-service-type
719 hd-idle-shepherd-service)))
720 (default-value (hd-idle-configuration))
721 (description "Run @command{hd-idle}, which spins down hard disks that have
722not been accessed for a configurable period of time.")))