Bu tuhaf seyrek dosya işleme / tmpfs ne açıklayabilir?


14

Benim üzerinde ext4dosya sistemi bölme ben aşağıdaki kodu çalıştırabilirsiniz:

fs="/mnt/ext4"

#create sparse 100M file on ${fs}
dd if=/dev/zero \
   of=${fs}/sparse100M conv=sparse seek=$((100*2*1024-1)) count=1 2> /dev/null

#show its actual used size before
echo "Before:"
ls ${fs}/sparse100M -s

#setting the sparse file up as loopback and run md5sum on loopback
losetup /dev/loop0 ${fs}/sparse100M 
md5sum /dev/loop0

#show its actual used size afterwards
echo "After:"
ls ${fs}/sparse100M -s

#release loopback and remove file
losetup -d /dev/loop0
rm ${fs}/sparse100M

hangi sonuç verir

Before:
0 sparse100M
2f282b84e7e608d5852449ed940bfc51  /dev/loop0
After:
0 sparse100M

Tmpfs'de olduğu gibi aynı şeyi yapmak:

fs="/tmp"

verim

Before:
0 /tmp/sparse100M
2f282b84e7e608d5852449ed940bfc51  /dev/loop0
After:
102400 /tmp/sparse100M

temelde sadece verileri okumamı beklediğim bir şey, seyrek dosyanın "balon gibi patlamasına" neden olduğu anlamına gelir?

Bunun dosya tmpfssistemindeki seyrek dosya için daha az mükemmel destek ve özellikle eksik FIEMAP ioctl nedeniyle olduğunu düşünüyorum, ancak bu davranışa ne neden olduğundan emin değilim? Bana söyler misin?


hum. Örneğin, seyrek bir sayfanın mmap () düzenlenmesi gerektiğinde kullanılabilen paylaşılan (yazma üzerine kopya) sıfır sayfası vardır. Bu yüzden neden seyrek bir tmpfs dosyasından herhangi bir okuma türünün gerçek bellek tahsis edilmesini gerektirdiğinden emin değilim. lwn.net/Articles/517465 . Bu, doğrudan io kullanmak için döngü dönüşümünün bir yan etkisi olup olmadığını merak ettim, ancak tmpfs'de yeni döngü türünü kullanmaya çalıştığınızda herhangi bir fark olmamalıdır. spinics.net/lists/linux-fsdevel/msg60337.html
sourcejedi

belki bu SO olsaydı bir cevap alabilir? sadece bir düşünce

1
/ Tmp çıktısının Öncesi / Sonrası farklı dosyaları vardır. Bu bir yazım hatası mı? Önce: 0 / tmp / sparse100 (sonunda M olmadan) Sonra: 102400 / tmp / sparse100M (sondaki M ile).
YoMismo

@YoMismo, evet sadece küçük bir yazım hatasıydı
humanityANDpeace

Yanıtlar:


4

Öncelikle , bu tür konular hakkında kafa karıştırıcı yalnız değilsiniz .

Bu sadece bunlarla sınırlı değildir, tmpfsaynı zamanda NFSv4 ile belirtilen bir endişe kaynağıdır .

Bir uygulama seyrek bir dosyada 'delikler' okursa, dosya sistemi boş blokları sıfırlarla dolu "gerçek" bloklara dönüştürür ve uygulamaya geri döndürür.

Bir md5sumdosyayı taramaya çalışırken açıkça bunu sıralı bir sırayla yapmayı seçer , bu da md5sum'un ne yapmaya çalıştığına bağlı olarak çok mantıklıdır.

Dosyada temel olarak "delikler" olduğundan, bu sıralı okuma (bazı durumlarda) dosyayı doldurmak için yazma benzeri işlemde bir kopyaya neden olacaktır. Bu daha sonra fallocate()dosya sisteminde desteklendiği gibi uygulanıp uygulanmadığı konusunda daha derin bir sorunla karşılaşır FALLOC_FL_PUNCH_HOLE.

Neyse ki, sadece bunu tmpfsdesteklemekle kalmaz, aynı zamanda delikleri "kazmak" için bir mekanizma vardır.

CLI yardımcı programını kullanarak fallocatebu delikleri başarılı bir şekilde algılayabilir ve yeniden kazabiliriz.

Başı man 1 fallocate:

-d, --dig-holes
      Detect and dig holes.  This makes the file sparse in-place, without
      using extra disk space.  The minimum size of the hole depends on
      filesystem I/O  block size (usually 4096 bytes).  Also, when using
      this option, --keep-size is implied.  If no range is specified by
      --offset and --length, then the entire file is analyzed for holes.

      You can think of this option as doing a "cp --sparse" and then
      renaming the destination file to the original, without the need for
      extra disk space.

      See --punch-hole for a list of supported filesystems.

fallocateolsa dosya düzeyinde çalışır ve md5sum bir blok cihaza (sıralı okumalar talep) karşı çalıştırırken fallocate()sistem aramasının nasıl çalışması gerektiği arasındaki boşluğu açarsınız. Bunu çalışırken görebiliriz:

Eylemde, örneğinizi kullanarak aşağıdakileri görüyoruz:

$ fs=$(mktemp -d)
$ echo ${fs}
/tmp/tmp.ONTGAS8L06
$ dd if=/dev/zero of=${fs}/sparse100M conv=sparse seek=$((100*2*1024-1)) count=1 2>/dev/null
$ echo "Before:" "$(ls ${fs}/sparse100M -s)"
Before: 0 /tmp/tmp.ONTGAS8L06/sparse100M
$ sudo losetup /dev/loop0 ${fs}/sparse100M
$ sudo md5sum /dev/loop0
2f282b84e7e608d5852449ed940bfc51  /dev/loop0
$ echo "After:" "$(ls ${fs}/sparse100M -s)"
After: 102400 /tmp/tmp.ONTGAS8L06/sparse100M
$ fallocate -d ${fs}/sparse100M
$ echo "After:" "$(ls ${fs}/sparse100M -s)"
After: 0 /tmp/tmp.ONTGAS8L06/sparse100M

Şimdi ... bu temel sorunuza cevap veriyor. Benim genel sloganım "garip olsun" bu yüzden daha fazla kazdık ...

$ fs=$(mktemp -d)
$ echo ${fs}
/tmp/tmp.ZcAxvW32GY
$ dd if=/dev/zero of=${fs}/sparse100M conv=sparse seek=$((100*2*1024-1)) count=1 2>/dev/null
$ echo "Before:" "$(ls ${fs}/sparse100M -s)"
Before: 0 /tmp/tmp.ZcAxvW32GY/sparse100M
$ sudo losetup /dev/loop0 ${fs}/sparse100M
$ echo "After:" "$(ls ${fs}/sparse100M -s)"
After: 1036 /tmp/tmp.ZcAxvW32GY/sparse100M
$ sudo md5sum ${fs}/sparse100M
2f282b84e7e608d5852449ed940bfc51  /tmp/tmp.ZcAxvW32GY/sparse100M
$ echo "After:" "$(ls ${fs}/sparse100M -s)"
After: 1036 /tmp/tmp.ZcAxvW32GY/sparse100M
$ fallocate -d ${fs}/sparse100M
$ echo "After:" "$(ls ${fs}/sparse100M -s)"
After: 520 /tmp/tmp.ZcAxvW32GY/sparse100M
$ sudo md5sum ${fs}/sparse100M
2f282b84e7e608d5852449ed940bfc51  /tmp/tmp.ZcAxvW32GY/sparse100M
$ echo "After:" "$(ls ${fs}/sparse100M -s)"
After: 520 /tmp/tmp.ZcAxvW32GY/sparse100M
$ fallocate -d ${fs}/sparse100M
$ echo "After:" "$(ls ${fs}/sparse100M -s)"
After: 516 /tmp/tmp.ZcAxvW32GY/sparse100M
$ fallocate -d ${fs}/sparse100M
$ sudo md5sum ${fs}/sparse100M
2f282b84e7e608d5852449ed940bfc51  /tmp/tmp.ZcAxvW32GY/sparse100M
$ echo "After:" "$(ls ${fs}/sparse100M -s)"
After: 512 /tmp/tmp.ZcAxvW32GY/sparse100M
$ fallocate -d ${fs}/sparse100M
$ echo "After:" "$(ls ${fs}/sparse100M -s)"
After: 0 /tmp/tmp.ZcAxvW32GY/sparse100M
$ sudo md5sum ${fs}/sparse100M
2f282b84e7e608d5852449ed940bfc51  /tmp/tmp.ZcAxvW32GY/sparse100M
$ echo "After:" "$(ls ${fs}/sparse100M -s)"
After: 0 /tmp/tmp.ZcAxvW32GY/sparse100M

Sen sadece hareket görüyoruz gerçekleştirenlosetup seyrek dosyanın boyutunu değiştirir. Böylece bu tmpfs, HOLE_PUNCH mekanizmasının fallocateve blok cihazlarının kesiştiği yerin ilginç bir kombinasyonu haline gelir .


2
Cevabınız için teşekkürler. Ben tmpfsseyrek dosyaları ve punch_hole destekler farkındayım . Bu kadar kafa karıştırıcı yapan şey budur - bunu tmpfs destekler , öyleyse neden bir döngü cihazından okurken seyrek delikleri doldursun? losetupdosya boyutunu değiştirmez, ancak çoğu sistemde daha sonra aşağıdaki gibi içerik için taranan bir blok cihazı oluşturur: bir bölüm tablosu var mı? UUID olan bir dosya sistemi var mı? o zaman bir / dev / disk / by-uuid / symlink oluşturmalı mıyım? Ve bu okumalar zaten seyrek dosyanın bazı bölümlerinin tahsis edilmesine neden oluyor, çünkü bazı gizemli nedenlerden dolayı , tmpfs (bazı) okumaları doldurur.
frostschutz

1
" Sıralı okuma (bazı durumlarda) yazma gibi işlemlerde bir kopyaya neden olacak " diye açıklayabilir misiniz , lütfen? Bir okuma işleminin yazma eyleminde bir kopyayı nasıl tetikleyeceğini merak ediyorum. Teşekkürler!
roaima

Bu tuhaf. Sistemimde aynı adımları bir komut dosyasında değil, el ile de izledim. Önce OP gibi 100M dosyası yaptım. Sonra adımları sadece 10MB'lık bir dosya ile tekrarladım. İlk sonuç: ls -s sparse100M 102400 idi. Ancak 10MB dosyasındaki ls -s sadece 328 bloktu. ??
Patrick Taylor

1
@PatrickTaylor ~ 328K, UUID tarayıcıları geldikten sonra kullanılanlarla ilgilidir, ancak tam okuma için döngü cihazına cat / md5sum eklemediniz.
frostschutz

1
Döngü çekirdek modülü (in loop.c) için kaynak kazıyordum ve iki ilgili fonksiyon olduğunu gördüm : lo_read_simple& lo_read_transfer. Düşük seviyeli bellek ayırma işlemlerinde bazı küçük farklılıklar vardır ... lo_read_transferaslında bir arama yaparken slab.h( GFP_NOIO) ' den engellenmeyen io ister alloc_page(). lo_read_simple()diğer yandan performans göstermiyor alloc_page().
Brian Redbeard
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.