Discos externos WD Red conectados a um Raspberry Pi girando muito cedo

2

Tenho dois discos rígidos externos WD Red conectados a um Raspberry Pi.
Eles giram depois de 2 minutos, o que é irritantemente rápido e eu sempre tenho que esperar eles girarem.

Eu li que hdparm não funciona com discos WD. Eu testei hdparm -I | grep level e não recebi nenhuma saída.

Eu li sobre hd-idle , mas pelo que entendi, ajuda com discos que nunca ficam em espera.

O que posso fazer para aumentar o tempo limite de espera?

edit: testei hdparm -S , efeito zero.

    
por Markonius 03.02.2018 / 16:48

2 respostas

0

Você pode escrever sua própria versão do hd-idle que faz o oposto, ou seja, faz um keep-awake fazendo algum acesso na unidade de disco antes que ele normalmente queira ficar ocioso. Mas você obviamente precisa distinguir quando realmente deixar ir e ter o disco dormindo.

Aqui está uma tentativa com um script perl. Você não precisa ser root para executá-lo, mas você precisa configurar algum arquivo no disco que você pode ler para fazer o keep-awake. Como o hd-idle, ele pesquisa as estatísticas de leitura / gravação do disco em /sys/ . Quando nenhuma E / S tiver sido feita pelo tempo apropriado, uma pequena leitura é feita a partir do arquivo keep-awake usando o flag O_DIRECT para garantir que uma E / S real seja feita. Isso deve apenas adicionar 1 ao total de estatísticas de leitura / gravação, para que possamos detectar se alguma outra E / S real também aconteceu na próxima pesquisa.

#!/usr/bin/perl
# stop standby of idle disc which doesnt support hdparm -S 12
# for stat fields see kernel src Documentation/iostats.txt
# https://unix.stackexchange.com/a/422138/119298
use strict;
use Fcntl;

my $device = 'sda';
my $filename = '/mnt/myfs/lost+found/tickle';

# create tickle file for test. or use any readonly non-empty file
if(! -s $filename){
    open(FILE,">$filename") or die $!;
    print FILE "used to keep disk from sleeping\n" or die $!;
    close(FILE) or die $!;
}
sysopen(FILE,$filename,O_RDONLY|O_DIRECT) or die $!;

my $minidle = 2*60;  # seconds of real idle before need to tweak awake
my $maxidle = 10*60; # seconds of false idle before allow to sleep
open(STAT,"/sys/block/$device/stat") or die;
my ($lasttot,$timechanged,$done);

# create block aligned buffer for O_DIRECT read
my $bufsize = 4096;
my $align = 512;
my $buf = 'x' x ($align+$bufsize);
my $offset = unpack("J", pack "p", $buf) % $align;
$offset = $align-$offset if $offset;

while(){
    my @fields = split(' ',<STAT>);
    # fields: 0 reads completed ok, 4 writes completed ok.  may wrap
    my $tot = $fields[0]+$fields[4];
    if($tot==$lasttot){
        my $idle = time()-$timechanged;
        print "$device idle $idle secs\n";
        if($done){
            # let it sleep some more
        }elsif($idle>=$maxidle){ # let it really sleep now
            print "$device sleep now after $idle secs\n";
            $done = 1;  
        }elsif($idle>=$minidle){ # tickle to stay awake
            sysseek(FILE,0,Fcntl::SEEK_SET)==0 or die $!;
            sysread(FILE,$buf,$bufsize,$offset)>0 or die $!;
            $lasttot++;
        } # else builtin hardware timeout not reached yet
    }else{
        $timechanged = time();
        $lasttot = $tot;
        $done = 0;
    }
    seek(STAT,0,0);
    sleep(55);
}

Você precisa definir $device para o nome do disco e $filename para o nome de um arquivo não vazio existente ou de um arquivo que possa ser criado no disco. Em $minidle , precisamos do tempo em que o disco normalmente fica inativo sozinho e em $maxidle o tempo que desejamos. forçá-lo a permanecer ativo. O tempo de pesquisa é definido no sleep() no final.

    
por 05.02.2018 / 23:09
0

Embora a resposta do meuh seja a resposta certa para essa pergunta, minha situação atual envolve invasão de software e eu sendo um imundo milenial

Eu reimplementou a solução do meuh no Python usando as escritas em vez das leituras.

import time
import datetime
import os

statFile = "/sys/block/<yourdevicehere>/stat"
logFile = "/some/file/on/another/drive.log"
dummyFile = "/some/file/on/drive/in/question"
updateInterval = 60 # seconds
keepAwakeTime = 30 * 60 # seconds
keepAwakeIOCount = 12 # empirically "proven"

# Clear the log file
open(logFile, "w").close()

def getIOCount():
    with open(statFile, "r") as fobj:
        fileContents = fobj.read()
    stats = fileContents.split()
    readCount = int(stats[0])
    writeCount = int(stats[4])
    return readCount + writeCount

# ==== main loop ==== #

maxIODiff = 0
averageIODiff = 0
diffCount = 0

previousIOCount = getIOCount()
timer = 0
while True:
    ioCount = getIOCount()
    if ioCount > previousIOCount:
        timer = keepAwakeTime

    ioDiff = ioCount - previousIOCount
    if ioDiff > maxIODiff:
        maxIODiff = ioDiff
    averageIODiff = (averageIODiff * diffCount + ioDiff) / (diffCount + 1)
    diffCount += 1

    previousIOCount = ioCount

    if timer > 0:
        line = str(ioDiff) + " " + str(maxIODiff) + " " + str(averageIODiff) + " " + datetime.datetime.now().strftime("%H:%M:%S") + "\n"
        with open(dummyFile, "w") as dummy:
            dummy.write(line)
            dummy.flush()
            os.fsync(dummy.fileno()),
        with open(logFile, "a") as log:
            log.write(line)
        previousIOCount += keepAwakeIOCount

    timer -= updateInterval
    time.sleep(updateInterval)

Embora este seja tecnicamente menos correto do que a solução do meuh, não consigo analisar o Perl e parece funcionar bem na minha configuração. E eu senti vontade de codificá-lo sozinho.

    
por 27.02.2018 / 14:32