ループデバイスをアトミックに割り当てる方法は?


11

私はいくつかのディスクイメージを処理するためにいくつかのシェルスクリプトを書いており、いくつかのディスクイメージにアクセスするにはループデバイスを使用する必要があります。ただし、プログラムを競合状態にさらさずにループデバイスを適切に割り当てる方法がわかりません。

losetup -fは次の未割り当てのループデバイスを取得し、そのループデバイスを次のように割り当てるために使用できることを知っています。

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

しかし、プログラムの複数のインスタンスを同時に実行したい場合、これはほぼ競合状態の教科書の例であり、それは私をかなり悩ませます。このプログラムの複数のインスタンスを実行している場合、または他のプログラムもループデバイスを取得しようとしている場合、各プロセスは次の呼び出しの前にループデバイスを割り当てることができないlosetup -f場合があります。その場合、両方のプロセスが同じループであると見なします。デバイスは利用可能ですが、入手できるのは1つだけです。

これに外部同期を使用することもできますが、(可能な場合は)追加の複雑さを避けたいです。また、ループデバイスを使用する他のプログラムは、思いついた同期を尊重しない可能性があります。

この潜在的な競合状態を回避するにはどうすればよいですか?理想的には、たとえば次のようなコマンドを使用して、ループデバイスをアトミックに検出およびバインドできるようにしたいと考えています。

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

ただし、それを行うと、$ldループデバイスパスに割り当てられず、sudoアウトを移動すると、sudo ld=$(losetup -f myfile.img)アクセス許可エラーが発生します。

回答:


13

これは、同時実行性の典型的な問題です。リソースを割り当てるとき、リソースが解放されていることをアトミックに決定して予約する必要があります。そうでない場合、別のプロセスが、リソースが解放されていることを確認してから予約するまでの間にリソースを予約できます。

使用していますlosetupの自動割り当てモードを(-f)、およびパス--showそれがループデバイスパスを印刷するためにオプションを選択します。

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

このオプションは、バージョン2.13以降、util-linuxに存在しています(最初はとして追加されまし-s--showが、すべてのリリースバージョンでサポートされており、最近のバージョンでは-sオプション名が削除されています)。残念ながら、BusyBoxバージョンにはありません。

Linuxカーネルのバージョン3.1では、新しいデバイスを介して、ループデバイス割り当て操作をカーネルで直接実行する方法が導入されまし/dev/loop-control。このメソッドは、util-linux 2.21以降でのみサポートされています。カーネル<3.1またはutil-linux <2.21の場合、losetupプログラムはループデバイスエントリを列挙して予約します。ただし、コードで競合状態を確認できません。安全である必要がありますが、小さなウィンドウが表示され、その間は、すべてのデバイスが割り当てられていると誤って報告されます。


何の</dev/ttyため?
ステファンChazelas

1
前回私が試したのはlosetup --find --showレースです。for i in {1..100}; do losetup -f -s $i & done100ループデバイスを提供しませんでした。ループデバイスは、通常は問題にならないほど一般的ではありません。それができる場合は、独自のロックを作成するか、正しいループデバイスが後付けとして作成されたことを確認することです。
frostschutz

@frostschutz losetupは失敗する可能性があります(たとえば、ループエントリが不足しているため)。デバイス名が報告された場合、それは正常に割り当てられたデバイスです。以前のバージョンには、割り当てが失敗した場合でもデバイス名を書き出すバグがありましたか?カーネル3.1以降にカーネル内割り当て用のインターフェイスが存在することがソースコードでわかりlosetupます。検索を実行するためのユーティリティを必要とする古いインターフェイスのバグですか?
Gilles「SO-邪悪なことをやめなさい」

ああ、確かに最近のバージョンでは修正されているようです。util-linux-2.26.2は機能しているようで、util-linux-2.24.1が繰り返し印刷する/dev/loop14などして、最終的にデバイスが完全になくなっている可能性があります。多分修正はの好意によるものであり/dev/loop-control、それはただ見るために使用されました/proc/partitions...
frostschutz

@frostschutz util-linux 2.21が存在losetupする/dev/loop-control場合は使用するため、競合状態になる可能性はないようです。割り当てはカーネルで行われ、デバイスパスの出力がユーティリティの最後の処理です。
Gilles 'SO-悪をやめる'

6

私はそれを考え出した。許可に関する問題がどのようになっているのかはわかりませんが、代わりに最初に撮影して、後でこのように尋ねることができます。

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

2

あなたが使うことができますflock

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

ここでの考え方はflock、ループデバイスファイルを試してみることです。同じスクリプトの別のインスタンスが最初に取得した場合、それは呼び出されlosetup $ld myfile.imgflock0を返します。レースに敗れたスクリプトはlosetup呼び出されず、flock1を返し、ループが繰り返されます。

詳細については、を参照してくださいman flock


0

ループバックデバイスとしてイメージを処理したい場合、それをファイルシステムとしてマウントし、コンテンツを操作するmountだけであれば、コマンドが自動的にこれを処理できます。

mount -o loop myfile.img /tmp/mountpoint

実際、私の場合、特にマウントしないようにしたいのですが、ファイルシステムではなくブロックデバイスとして使用しています。
AJMansfield、2015年

@AJMansfieldそれをマウントする以外に、ファイルではできないブロックデバイスで何ができますか?
Random832

フルディスクのbtrfsセットアップでは、スワップスペースとしてフォーマットすることはできません。btrfsはスワップファイルに必要な操作をサポートしておらず、フルディスクのbtrfsセットアップでは実際のスワップパーティションを作成できないため、このファイルをスワップスペースに使用するつもりでした。
AJMansfield
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.