Bagaimana cara mengalokasikan perangkat loop secara atom?

11

Saya menulis beberapa skrip shell untuk menangani beberapa hal gambar disk, dan saya perlu menggunakan perangkat loop untuk mengakses beberapa gambar disk. Namun, saya tidak yakin bagaimana cara mengalokasikan perangkat loop dengan benar tanpa memaparkan program saya ke kondisi balapan.

Saya tahu bahwa saya dapat menggunakan losetup -funtuk mendapatkan perangkat loop yang tidak teralokasi berikutnya, dan kemudian mengalokasikan perangkat loop seperti ini:

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

Namun, dalam kasus di mana saya ingin menjalankan beberapa contoh program pada saat yang sama, ini hampir merupakan contoh buku teks dari kondisi lomba, dan itu cukup mengganggu saya. Jika saya memiliki beberapa instance dari program ini berjalan, atau program lain yang mencoba juga mendapatkan perangkat loop, maka setiap proses mungkin tidak dapat mengalokasikan perangkat loop sebelum panggilan berikutnya losetup -f, dalam hal ini kedua proses akan berpikir bahwa loop yang sama perangkat tersedia, tetapi hanya satu yang bisa mendapatkannya.

Saya dapat menggunakan sinkronisasi eksternal untuk ini, tetapi saya ingin (jika mungkin) menghindari kompleksitas tambahan. Selain itu, program lain yang menggunakan perangkat loop sepertinya tidak akan menghargai sinkronisasi apa pun yang mungkin saya buat.

Bagaimana saya bisa menghindari kondisi lomba potensial ini? Idealnya, saya ingin dapat menemukan dan mengikat perangkat loop secara atom, misalnya dengan perintah seperti:

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

Namun, ketika saya melakukan itu, $ldtidak mendapatkan ditugaskan ke jalur perangkat loop, dan pindah sudokeluar, karena sudo ld=$(losetup -f myfile.img)memberikan kesalahan izin.

AJMansfield
sumber

Jawaban:

13

Ini adalah masalah klasik dalam konkurensi: ketika mengalokasikan sumber daya, Anda perlu menentukan secara atom bahwa sumber daya itu gratis dan mencadangkannya, jika tidak, proses lain dapat mencadangkan sumber daya tersebut di antara waktu Anda memeriksa apakah itu gratis dan saat Anda memesannya.

Gunakan losetupmode alokasi otomatis ( -f), dan berikan --showopsi untuk membuatnya mencetak jalur perangkat loop.

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

Opsi ini telah ada di util-linux sejak versi 2.13 ( awalnya ditambahkan sebagai-s , tetapi --showtelah didukung di semua versi yang dirilis dan versi terbaru telah menjatuhkan -snama opsi). Sayangnya versi BusyBox tidak memilikinya.

Versi 3.1 dari kernel Linux memperkenalkan metode untuk melakukan operasi alokasi perangkat loop langsung di kernel, melalui /dev/loop-controlperangkat baru . Metode ini hanya didukung sejak util-linux 2.21. Dengan kernel <3.1 atau util-linux <2.21, losetupprogram ini menghitung entri perangkat loop untuk memesannya. Saya tidak bisa melihat kondisi lomba dalam kode; itu harus aman tetapi mungkin memiliki jendela kecil di mana ia akan salah melaporkan bahwa semua perangkat dialokasikan meskipun ini tidak terjadi.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
Untuk apa </dev/tty?
Stéphane Chazelas
1
Terakhir kali saya mencoba, bahkan losetup --find --showbalapan. for i in {1..100}; do losetup -f -s $i & donetidak memberi saya 100 perangkat loop. Perangkat loop tidak cukup umum untuk itu tidak menjadi masalah secara normal; jika itu satu-satunya pilihan Anda adalah membuat kunci Anda sendiri dan / atau memeriksa apakah perangkat loop yang benar dibuat sebagai renungan.
frostschutz
@frostschutz losetupmungkin gagal (misalnya karena Anda kehabisan entri loop), tetapi jika melaporkan nama perangkat, itu adalah perangkat yang berhasil dialokasikan. Apakah versi sebelumnya memiliki bug yang menyebabkannya menuliskan nama perangkat meskipun alokasi gagal? Saya melihat dalam kode sumber bahwa antarmuka untuk alokasi in-kernel hanya ada sejak kernel 3.1, apakah mungkin bug dengan antarmuka yang lebih lama yang memerlukan losetuputilitas untuk melakukan pencarian?
Gilles 'SANGAT berhenti menjadi jahat'
Oh, tampaknya memang diperbaiki di versi yang lebih baru. util-linux-2.26.2 tampaknya berfungsi, util-linux-2.24.1 berulang kali mencetak /dev/loop14dan semacamnya dan perangkat mungkin hilang sama sekali pada akhirnya. Mungkin perbaikannya adalah dari /dev/loop-control, dulu hanya melihat /proc/partitions...
frostschutz
@ frostschutz Sejak util-linux 2.21, losetupdigunakan /dev/loop-controljika ada, dan itu sepertinya tidak memiliki kondisi ras: alokasi yang terjadi di kernel dan mencetak jalur perangkat adalah hal terakhir yang dilakukan utilitas.
Gilles 'SANGAT berhenti menjadi jahat'
6

Saya menemukan jawabannya. Meskipun saya tidak yakin bagaimana masalah dengan izinnya, saya bisa memotret terlebih dahulu dan bertanya kemudian seperti ini:

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

Anda bisa menggunakan flock:

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

Idenya di sini adalah bahwa Anda mencoba dan flockfile perangkat loop; jika instance lain dari skrip yang sama mendapatkannya terlebih dahulu, ia akan memanggil losetup $ld myfile.imgdan flockakan mengembalikan 0. Untuk skrip yang kehilangan balapan, losetuptidak akan dipanggil dan flockakan mengembalikan 1, menyebabkan loop berulang.

Untuk lebih banyak lihat man flock.

goldilocks
sumber
0

Jika semua yang ingin Anda lakukan dengan gambar sebagai perangkat loopback adalah me-mount-nya sebagai sistem file dan bekerja dengan konten, mountperintah ini dapat menangani hal ini secara otomatis.

mount -o loop myfile.img /tmp/mountpoint
Random832
sumber
Sebenarnya, dalam kasus saya, saya khususnya ingin itu tidak dipasang - saya menggunakannya sebagai perangkat blok bukan sistem file.
AJMansfield
@ AJMansfield Selain memasangnya, apa yang dapat Anda lakukan dengan perangkat blok yang tidak dapat Anda lakukan dengan file?
Random832
Anda tidak dapat memformatnya sebagai ruang swap pada pengaturan btrf disk penuh. Saya bermaksud menggunakan file untuk ruang swap, karena btrfs tidak mendukung operasi yang diperlukan untuk file swap, dan saya tidak dapat memiliki partisi swap nyata dengan setup btrf disk penuh.
AJMansfield