¿Cómo asignar atómicamente un dispositivo de bucle?

Estoy escribiendo algunos scripts de shell para manejar algunas imágenes de disco, y necesito usar dispositivos de bucle para acceder a algunas imágenes de disco. Sin embargo, no estoy seguro de cómo asignar correctamente un dispositivo de bucle sin exponer mi progtwig a una condición de carrera.

Sé que puedo usar losetup -f para get el siguiente dispositivo de bucle sin asignar, y luego asignar ese dispositivo de bucle así:

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

Sin embargo, en el caso en que quiero ejecutar varias instancias del progtwig al mismo time, esto es casi un ejemplo de libro de text de una condición de carrera, y eso me molesta bastante. Si tuviera varias instancias de este progtwig ejecutándose u otros progtwigs intentando también get un dispositivo de bucle, entonces cada process podría no ser capaz de asignar el dispositivo de bucle antes de que el siguiente llame a losetup -f , en cuyo caso ambos processs pensarían que el mismo dispositivo de bucle está disponible, pero solo uno puede getlo.

Podría usar la synchronization externa para esto, pero me gustaría (si es posible) evitar una complejidad adicional. Además, otros progtwigs que usan dispositivos de bucle probablemente no respeten la synchronization que se me ocurra.

¿Cómo puedo evitar esta potencial condición de carrera? Idealmente, me gustaría poder descubrir y vincular el dispositivo de bucle atómicamente, por ejemplo con un command como:

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

Sin embargo, cuando lo hago, $ld no se asigna a la ruta del dispositivo de bucle, y mover el sudo out, como en sudo ld=$(losetup -f myfile.img) da errores de permiso.

Este es un problema clásico en concurrency: al asignar un recurso, debe determinar atómicamente que el recurso es gratuito y reservarlo, de lo contrario, otro process podría reservar el recurso entre el momento en que comtesting que es gratuito y el time que lo reserva.

Utilice el modo de asignación automática de losetup ( -f ) y pase la opción --show para que imprima la ruta del dispositivo de bucle.

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

Esta opción ha estado presente en util-linux desde la versión 2.13 ( inicialmente se agregó como -s , pero --show ha sido admitido en todas las versiones publicadas y las versiones recientes han omitido el -s nombre de opción). Lamentablemente, la versión BusyBox no lo tiene.

La versión 3.1 del kernel de Linux introdujo un método para realizar la operación de asignación del dispositivo de bucle directamente en el kernel, a través del nuevo dispositivo /dev/loop-control . Este método solo es compatible desde util-linux 2.21. Con kernel <3.1 o util-linux <2.21, el progtwig losetup enumera las inputs del dispositivo de bucle para reservar uno. Sin embargo, no puedo ver una condición de carrera en el código; debería ser seguro, pero podría tener una pequeña window durante la cual informará incorrectamente que todos los dispositivos están asignados, aunque este no sea el caso.

Me lo imaginé. Aunque no estoy seguro de cómo es el problema con el permiso, puedo disparar primero y preguntar más tarde de esta manera:

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

Puedes usar flock :

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

La idea aquí es que intentes flock el file del dispositivo de bucle; si otra instancia de la misma secuencia de commands la adquiere primero, llamará a losetup $ld myfile.img y la flock devolverá 0. Para la secuencia de commands que pierde la carrera, no se losetup y la flock devolverá 1, causando el ciclo repetir.

Para más ver man flock .

Si todo lo que desea hacer con la image como un dispositivo de retroalimentación es montarlo como un sistema de files y trabajar con los contenidos, el command de mount puede encargarse de esto automáticamente.

 mount -o loop myfile.img /tmp/mountpoint