Come allocare atomicamente un dispositivo loop?


11

Sto scrivendo alcuni script di shell per gestire alcune cose relative alle immagini del disco e ho bisogno di usare dispositivi loop per accedere ad alcune immagini del disco. Tuttavia, non sono sicuro di come allocare correttamente un dispositivo loop senza esporre il mio programma a una condizione di gara.

So che posso usare losetup -fper ottenere il prossimo dispositivo loop non allocato e quindi allocare quel dispositivo loop in questo modo:

ld=$(losetup -f)
sudo losetup $ld myfile.img
dostuffwith $ld

Tuttavia, nel caso in cui voglio eseguire più istanze del programma contemporaneamente, questo è quasi un esempio da manuale di una condizione di gara, e questo mi preoccupa parecchio. Se avessi istanze multiple di questo programma in esecuzione, o altri programmi che cercassero di ottenere anche un dispositivo loop, ogni processo potrebbe non essere in grado di allocare il dispositivo loop prima che il successivo richiami losetup -f, nel qual caso entrambi i processi penserebbero che lo stesso loop il dispositivo è disponibile, ma solo uno può ottenerlo.

Potrei usare la sincronizzazione esterna per questo, ma vorrei (se possibile) evitare ulteriore complessità. Inoltre, altri programmi che usano dispositivi a circuito chiuso non rispetterebbero probabilmente qualsiasi sincronizzazione che mi venga in mente.

Come posso evitare questa potenziale condizione di gara? Idealmente, vorrei essere in grado di scoprire e associare atomicamente il dispositivo loop, ad esempio con un comando come:

ld=$(sudo losetup -f myfile.img)
dostuffwith $ld

Tuttavia, quando lo faccio, $ldnon mi viene assegnato il percorso del dispositivo loop e lo spostamento sudo, come in sudo ld=$(losetup -f myfile.img)dà errori di autorizzazione.

Risposte:


13

Questo è un classico problema in concorrenza: quando si alloca una risorsa, è necessario determinare atomicamente che la risorsa è libera e prenotarla, altrimenti un altro processo potrebbe riservare la risorsa tra il momento in cui si verifica che sia libera e il tempo in cui la si riserva.

Utilizzare losetupla modalità di allocazione automatica ( -f) e passare l' --showopzione per farlo stampare il percorso del dispositivo loop.

ld=$(sudo losetup --show -f /tmp/1m)

Questa opzione è presente in util-linux dalla versione 2.13 ( inizialmente aggiunta come-s , ma --showè stata supportata in tutte le versioni rilasciate e le versioni recenti hanno abbandonato il -snome dell'opzione). Sfortunatamente la versione di BusyBox non ce l'ha.

La versione 3.1 del kernel Linux ha introdotto un metodo per eseguire l'operazione di allocazione del dispositivo in loop direttamente nel kernel, tramite il nuovo /dev/loop-controldispositivo. Questo metodo è supportato solo da util-linux 2.21. Con kernel <3.1 o util-linux <2.21, il losetupprogramma enumera le voci del dispositivo loop per riservarne una. Non riesco a vedere una condizione di competizione nel codice però; dovrebbe essere sicuro ma potrebbe avere una piccola finestra durante la quale segnalerà erroneamente che tutti i dispositivi sono allocati anche se non è così.


A cosa serve </dev/tty?
Stéphane Chazelas,

1
L'ultima volta che ho provato, anche le losetup --find --showgare. for i in {1..100}; do losetup -f -s $i & donenon mi ha dato 100 dispositivi loop. I dispositivi loop sono abbastanza rari da non importare normalmente; se lo fa l'unica opzione è quella di creare i propri blocchi e / o verificare che il dispositivo loop corretto sia stato creato come ripensamento.
frostschutz,

@frostschutz losetuppotrebbe non riuscire (ad es. perché hai esaurito le voci del loop), ma se riporta un nome di dispositivo, questo è il dispositivo che è stato allocato correttamente. Le versioni precedenti avevano un bug che gli faceva scrivere un nome di dispositivo anche se l'allocazione non era riuscita? Vedo nel codice sorgente che l'interfaccia per l'allocazione nel kernel esiste solo dal kernel 3.1, è forse un bug con l'interfaccia precedente che richiede losetupall'utilità di fare la ricerca?
Gilles 'SO- smetti di essere malvagio'

Oh, sembra davvero che sia stato corretto nelle versioni più recenti. util-linux-2.26.2 sembra funzionare, util-linux-2.24.1 stampa ripetutamente /dev/loop14e così e il dispositivo potrebbe mancare del tutto alla fine. Forse la correzione è per gentile concessione /dev/loop-control, guardava solo /proc/partitions...
frostschutz,

@frostschutz Da util-linux 2.21, losetupusa /dev/loop-controlse presente, e non sembra che possa avere una condizione di competizione: l'allocazione avviene nel kernel e la stampa del percorso del dispositivo è l'ultima cosa che fa l'utilità.
Gilles 'SO- smetti di essere malvagio'

6

L'avevo capito. Anche se non sono sicuro di come sia il problema con l'autorizzazione, posso invece sparare prima e chiedere in seguito in questo modo:

sudo losetup -f myfile.img
ld=$(losetup -j myfile.img | grep -o "/dev/loop[0-9]*")
dostuffwith $ld

2

Puoi usare flock:

  tryagain=1
  while [[ $tryagain -ne 0 ]]; do
    ld=`losetup -f`
    flock -n $ld -c "losetup $ld myfile.img"
    tryagain=$?
  done

L'idea qui è che si tenta e flockil file del dispositivo loop; se un'altra istanza dello stesso script lo acquisisce per prima, verrà chiamato losetup $ld myfile.imge flockrestituirà 0. Per lo script che perde la corsa, losetupnon verrà chiamato e flockrestituirà 1, causando la ripetizione del loop.

Per di più vedi man flock.


0

Se tutto ciò che vuoi fare con l'immagine come dispositivo di loopback è montarlo come filesystem e lavorare con i contenuti, il mountcomando può occuparsene automaticamente.

mount -o loop myfile.img /tmp/mountpoint

In realtà, nel mio caso, in particolare voglio che non sia montato - lo sto usando come un dispositivo a blocchi, non un filesystem.
AJMansfield,

@AJMansfield Oltre a montarlo, cosa puoi fare con un dispositivo a blocchi che non puoi fare con un file?
Casuale 832,

Non è possibile formattarlo come spazio di swap su un'installazione btrfs a disco intero. Avevo intenzione di utilizzare il file per lo spazio di swap, poiché btrfs non supporta le operazioni necessarie per i file di swap e non posso avere una vera partizione di swap con una configurazione di btrfs su disco completo.
AJMansfield,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.