Mengamati hard disk menulis dalam ruang kernel (dengan driver / modul)

13

Mohon maaf sebelumnya jika postingan ini agak padat / berantakan, tapi saya kesulitan memformulasikannya dengan lebih baik ... Pada dasarnya, saya ingin mempelajari apa yang terjadi pada penulisan hard disk, dan saya ingin tahu:

  • Apakah pemahaman saya di bawah ini benar - dan jika tidak, di mana saya salah?
  • Apakah ada alat yang lebih baik untuk "menangkap" data log, tentang semua aspek yang terjadi pada PC, selama penulisan disk?

Secara lebih rinci - pertama, OS yang saya gunakan adalah:

$ uname -a
Linux mypc 2.6.38-16-generic #67-Ubuntu SMP Thu Sep 6 18:00:43 UTC 2012 i686 i686 i386 GNU/Linux

Jadi, saya memiliki sederhana berikut (misalnya pemeriksaan biasa untuk kegagalan operasi dilewati) Program user-space C, wtest.c:

#include <stdio.h>
#include <fcntl.h>  // O_CREAT, O_WRONLY, S_IRUSR

int main(void) {
  char filename[] = "/tmp/wtest.txt";
  char buffer[] = "abcd";
  int fd;
  mode_t perms = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;

  fd = open(filename, O_RDWR|O_CREAT, perms);
  write(fd,buffer,4);
  close(fd);

  return 0;
}

Saya membangun ini dengan gcc -g -O0 -o wtest wtest.c. Sekarang, karena saya mencoba menulis /tmp, saya perhatikan bahwa itu adalah direktori di bawah root /- jadi saya periksa mount:

$ mount
/dev/sda5 on / type ext4 (rw,errors=remount-ro,commit=0)
...
/dev/sda6 on /media/disk1 type ext4 (rw,uhelper=hal,commit=0)
/dev/sda7 on /media/disk2 type ext3 (rw,nosuid,nodev,uhelper=udisks,commit=0,commit=0,commit=0,commit=0,commit=0,commit=0)
...

Jadi, sistem file root saya /adalah satu partisi /dev/sdaperangkat (dan saya juga menggunakan partisi lain sebagai disk / mount "standalone"). Untuk menemukan driver untuk perangkat ini, saya menggunakan hwinfo:

$ hwinfo --disk
...
19: IDE 00.0: 10600 Disk
...
  SysFS ID: /class/block/sda
  SysFS BusID: 0:0:0:0
...
  Hardware Class: disk
  Model: "FUJITSU MHY225RB"
...
  Driver: "ata_piix", "sd"
  Driver Modules: "ata_piix"
  Device File: /dev/sda
...
  Device Number: block 8:0-8:15
...

Jadi, /dev/sdahard disk tampaknya ditangani oleh ata_piix(dan sd) driver.

$ grep 'ata_piix\| sd' <(gunzip </var/log/syslog.2.gz)
Jan 20 09:28:31 mypc kernel: [    1.963846] ata_piix 0000:00:1f.2: version 2.13
Jan 20 09:28:31 mypc kernel: [    1.963901] ata_piix 0000:00:1f.2: PCI INT B -> GSI 19 (level, low) -> IRQ 19
Jan 20 09:28:31 mypc kernel: [    1.963912] ata_piix 0000:00:1f.2: MAP [ P0 P2 P1 P3 ]
Jan 20 09:28:31 mypc kernel: [    2.116038] ata_piix 0000:00:1f.2: setting latency timer to 64
Jan 20 09:28:31 mypc kernel: [    2.116817] scsi0 : ata_piix
Jan 20 09:28:31 mypc kernel: [    2.117068] scsi1 : ata_piix
Jan 20 09:28:31 mypc kernel: [    2.529065] sd 0:0:0:0: [sda] 488397168 512-byte logical blocks: (250 GB/232 GiB)
Jan 20 09:28:31 mypc kernel: [    2.529104] sd 0:0:0:0: Attached scsi generic sg0 type 0
Jan 20 09:28:31 mypc kernel: [    2.529309] sd 0:0:0:0: [sda] Write Protect is off
Jan 20 09:28:31 mypc kernel: [    2.529319] sd 0:0:0:0: [sda] Mode Sense: 00 3a 00 00
Jan 20 09:28:31 mypc kernel: [    2.529423] sd 0:0:0:0: [sda] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
Jan 20 09:28:31 mypc kernel: [    2.674783]  sda: sda1 sda2 < sda5 sda6 sda7 sda8 sda9 sda10 >
Jan 20 09:28:31 mypc kernel: [    2.676075] sd 0:0:0:0: [sda] Attached SCSI disk
Jan 20 09:28:31 mypc kernel: [    4.145312] sd 2:0:0:0: Attached scsi generic sg1 type 0
Jan 20 09:28:31 mypc kernel: [    4.150596] sd 2:0:0:0: [sdb] Attached SCSI removable disk

Saya harus menarik dari syslog yang lebih lama karena saya banyak menangguhkan, tetapi di atas sepertinya potongan yang tepat dari syslog pada saat boot, di mana driver ata_piix(dan sd) menendang untuk pertama kalinya.

Titik kebingungan pertama saya adalah bahwa saya tidak dapat mengamati driver ata_piixatau sebaliknya sd:

$ lsmod | grep 'ata_piix\| sd'
$
$ modinfo sd
ERROR: modinfo: could not find module sd
$ modinfo ata_piix
ERROR: modinfo: could not find module ata_piix

Jadi pertanyaan pertama saya adalah - mengapa saya tidak dapat mengamati ata_piixmodul di sini, hanya di log waktu boot? Apakah karena ata_piix(dan sd) dibangun sebagai driver bawaan pada kernel (monolitik), dan bukan dibangun sebagai modul .kokernel (yang dapat dimuat) ?

Benar - jadi sekarang, saya mencoba mengamati apa yang terjadi setelah menjalankan program dengan ftracepelacak fungsi bawaan Linux.

sudo bash -c '
KDBGPATH="/sys/kernel/debug/tracing"
echo function_graph > $KDBGPATH/current_tracer
echo funcgraph-abstime > $KDBGPATH/trace_options
echo funcgraph-proc > $KDBGPATH/trace_options
echo 0 > $KDBGPATH/tracing_on
echo > $KDBGPATH/trace
echo 1 > $KDBGPATH/tracing_on ; ./wtest ; echo 0 > $KDBGPATH/tracing_on
cat $KDBGPATH/trace > wtest.ftrace
'

... dan di sini adalah potongan ftracelog tentang write:

4604.352690 | 0) wtest-31632 | | sys_write () {
 4604.352690 | 0) wtest-31632 | 0,750 kami | fget_light ();
 4604.352692 | 0) wtest-31632 | | vfs_write () {
 4604.352693 | 0) wtest-31632 | | rw_verify_area () {
 4604.352693 | 0) wtest-31632 | | security_file_permission () {
 4604.352694 | 0) wtest-31632 | | apparmor_file_permission () {
 4604.352695 | 0) wtest-31632 | 0,811 us | common_file_perm ();
 4604.352696 | 0) wtest-31632 | 2.198 kami | }
 4604.352697 | 0) wtest-31632 | 3.573 kami | }
 4604.352697 | 0) wtest-31632 | 4.979 kami | }
 4604.352698 | 0) wtest-31632 | | do_sync_write () {
 4604.352699 | 0) wtest-31632 | | ext4_file_write () {
 4604.352700 | 0) wtest-31632 | | generic_file_aio_write () {
 4604.352701 | 0) wtest-31632 | | mutex_lock () {
 4604.352701 | 0) wtest-31632 | 0,666 us | _cond_resched ();
 4604.352703 | 0) wtest-31632 | 1.994 us | }
 4604.352704 | 0) wtest-31632 | | __generic_file_aio_write () {
...
 4604.352728 | 0) wtest-31632 | | file_update_time () {
...
 4604.352732 | 0) wtest-31632 | 0,756 kami | mnt_want_write_file ();
 4604.352734 | 0) wtest-31632 | | __mark_inode_dirty () {
...
 4604.352750 | 0) wtest-31632 | | ext4_mark_inode_dirty () {
 4604.352750 | 0) wtest-31632 | 0,679 us | _cond_resched ();
 4604.352752 | 0) wtest-31632 | | ext4_reserve_inode_write () {
...
 4604.352777 | 0) wtest-31632 | | __ext4_journal_get_write_access () {
...
 4604.352795 | 0) wtest-31632 | | ext4_mark_iloc_dirty () {
...
 4604.352806 | 0) wtest-31632 | | __ext4_journal_stop () {
...
 4604.352821 | 0) wtest-31632 | 0.684 us | mnt_drop_write ();
 4604.352822 | 0) wtest-31632 | + 93.541 us | }
 4604.352823 | 0) wtest-31632 | | generic_file_buffered_write () {
 4604.352824 | 0) wtest-31632 | 0.654 kami | iov_iter_advance ();
 4604.352825 | 0) wtest-31632 | | generic_perform_write () {
 4604.352826 | 0) wtest-31632 | 0,709 us | iov_iter_fault_in_readable ();
 4604.352828 | 0) wtest-31632 | | ext4_da_write_begin () {
 4604.352829 | 0) wtest-31632 | | ext4_journal_start_sb () {
...
 4604.352847 | 0) wtest-31632 | 1.453 us | __block_write_begin ();
 4604.352849 | 0) wtest-31632 | + 21.128 us | }
 4604.352849 | 0) wtest-31632 | | iov_iter_copy_from_user_atomic () {
 4604.352850 | 0) wtest-31632 | | __kmap_atomic () {
...
 4604.352863 | 0) wtest-31632 | 0,672 us | mark_page_accessed ();
 4604.352864 | 0) wtest-31632 | | ext4_da_write_end () {
 4604.352865 | 0) wtest-31632 | | generic_write_end () {
 4604.352866 | 0) wtest-31632 | | block_write_end () {
...
 4604.352893 | 0) wtest-31632 | | __ext4_journal_stop () {
...
 4604.352909 | 0) wtest-31632 | 0.655 kami | mutex_unlock ();
 4604.352911 | 0) wtest-31632 | 0,727 kami | generic_write_sync ();
 4604.352912 | 0) wtest-31632 | ! 212.259 us | }
 4604.352913 | 0) wtest-31632 | ! 213.845 us | }
 4604.352914 | 0) wtest-31632 | ! 215.286 kami | }
 4604.352914 | 0) wtest-31632 | 0.685 kami | __fsnotify_parent ();
 4604.352916 | 0) wtest-31632 | | fsnotify () {
 4604.352916 | 0) wtest-31632 | 0.907 kami | __srcu_read_lock ();
 4604.352918 | 0) wtest-31632 | 0.685 kami | __srcu_read_unlock ();
 4604.352920 | 0) wtest-31632 | 3.958 kami | }
 4604.352920 | 0) wtest-31632 | ! 228.409 us | }
 4604.352921 | 0) wtest-31632 | ! 231.334 us | }

Ini adalah titik kedua kebingungan saya - saya dapat mengamati ruang-pengguna yang write()dihasilkan dengan ruang-kernel sys_write(), seperti yang diharapkan; dan di dalam sys_write(), saya mengamati fungsi-fungsi yang berhubungan dengan keamanan (mis. apparmor_file_permission()), fungsi tulis "generik" (mis. generic_file_aio_write()), ext4fungsi-fungsi yang berhubungan dengan filesystem (misal ext4_journal_start_sb()) - tetapi saya tidak mengamati apapun yang berhubungan dengan ata_piix(atau sd) driver ?!

Halaman Tracing dan Profiling - Yocto Project menyarankan menggunakan blkpelacak ftraceuntuk mendapatkan informasi lebih lanjut tentang operasi perangkat blok, tetapi tidak melaporkan apa-apa bagi saya dengan contoh ini. Juga, Linux Filesystem Drivers - Annon Inglorion (tutorfs) menyarankan bahwa filesystems (can?) Juga diimplementasikan sebagai modul / driver kernel, dan saya menduga itu ext4juga berlaku.

Akhirnya, saya bisa bersumpah bahwa saya sebelumnya telah mengamati nama driver dalam tanda kurung di sebelah fungsi yang ditunjukkan oleh function_graphpelacak, tapi saya kira saya telah mencampuradukkan hal-hal - itu mungkin dapat muncul seperti itu di tumpukan (kembali) jejak, tetapi tidak dalam grafik fungsi. Selanjutnya, saya dapat memeriksa /proc/kallsyms:

$ grep 'piix\| sd\|psmouse' /proc/kallsyms
...
00000000 d sd_ctl_dir
00000000 d sd_ctl_root
00000000 d sdev_class
00000000 d sdev_attr_queue_depth_rw
00000000 d sdev_attr_queue_ramp_up_period
00000000 d sdev_attr_queue_type_rw
00000000 d sd_disk_class
...
00000000 t piix_init_sata_map
00000000 t piix_init_sidpr
00000000 t piix_init_one
00000000 t pci_fixup_piix4_acpi
...
00000000 t psmouse_show_int_attr        [psmouse]
00000000 t psmouse_protocol_by_type     [psmouse]
00000000 r psmouse_protocols    [psmouse]
00000000 t psmouse_get_maxproto [psmouse]
...

... dan memeriksa dengan sumber Linux / driver / ata / ata_piix.c , konfirmasikan bahwa eg piix_init_sata_mapmemang sebuah fungsi di ata_piix. Yang mungkin harus memberi tahu saya bahwa: modul yang dikompilasi dalam kernel (sehingga mereka menjadi bagian dari kernel monolitik) "kehilangan" informasi tentang modul mana mereka berasal; akan tetapi, modul yang dapat dimuat yang dibangun sebagai .koobjek kernel yang terpisah , menyimpan informasi tersebut (mis. yang [psmouse]ditunjukkan di atas dalam tanda kurung siku). Dengan demikian, juga ftracehanya bisa menampilkan informasi "modul berasal", hanya untuk fungsi-fungsi yang berasal dari modul kernel yang dapat dimuat. Apakah ini benar?

Di atas dipertimbangkan, ini adalah pemahaman yang saya miliki tentang proses saat ini:

  • Pada saat boot, ata_piixdriver membuat pemetaan memori DMA (?) Antara /dev/sdadan hard disk
    • karena ini, semua masa depan akses ke /dev/sdamelalui ata_piixakan transparan kepada kernel (yaitu, tidak dapat dilacak) - karena semua kernel akan melihat, hanya membaca / menulis ke lokasi memori (tidak harus memanggil fungsi kernel dapat dilacak tertentu), yang tidak dilaporkan oleh function_graphpelacak
  • Pada saat boot, sddriver selanjutnya akan "mem-parsing" partisi /dev/sda, membuatnya tersedia, dan mungkin menangani pemetaan memori antara partisi <-> perangkat disk
    • sekali lagi, ini harus membuat operasi akses melalui sdtransparan ke kernel
  • Karena keduanya ata_piixdan sddikompilasi dalam kernel, bahkan jika beberapa fungsinya akhirnya ditangkap oleh ftrace, kami tidak dapat memperoleh informasi dari modul mana fungsi-fungsi tersebut berasal (terlepas dari korelasi "manual" dengan file sumber)
  • Kemudian, mountbuat hubungan / ikatan antara partisi, dan driver sistem file yang sesuai (dalam hal ini ext4)
    • mulai saat ini, semua akses ke sistem file yang di-mount akan ditangani oleh ext4fungsi - yang dapat dilacak oleh kernel; tetapi seperti ext4yang dikompilasi dalam kernel, pelacak tidak dapat memberi kami informasi modul yang berasal
  • Jadi, tulisan "generik" yang diamati, disebut melalui ext4fungsi, pada akhirnya akan mengakses lokasi memori, yang pemetaannya dilakukan oleh ata_piix- tetapi selain itu, ata_piixtidak mengganggu langsung dengan transfer data (mungkin sedang ditangani oleh DMA (di luar prosesor) (s), dan karenanya transparan untuk itu).

Apakah pemahaman ini benar?

Beberapa pertanyaan yang terkait:

  • Dalam pengaturan saya di atas, saya dapat mengidentifikasi driver perangkat PCI ( ata_piix) dan driver sistem file ( ext4); tetapi apakah ada driver karakter atau blok yang digunakan di suatu tempat di jalur eksekusi "tulis", dan jika demikian, yang mana mereka?
  • Manakah dari driver yang akan menangani caching (sehingga operasi disk yang tidak perlu dilewati atau dioptimalkan?)
  • Saya tahu sebelumnya bahwa itu /dev/shmadalah sistem file dalam RAM; mount | grep shmbagi saya melaporkan: none on /dev/shm type tmpfs (rw,nosuid,nodev). Apakah itu berarti bahwa - berbeda dengan /dev/sda- sistem shmfile tidak memiliki pemetaan (DMA) dari alamatnya "sendiri" ke alamat bus ke perangkat; dan dengan demikian semua akses melalui tmpfsdriver filesystem berakhir di RAM yang sebenarnya?
sdaau
sumber
4
Hai sdaau. Ini adalah pertanyaan yang bagus, tetapi panjang posting ini berlebihan, dan ada beberapa pertanyaan di sana. Patut dipuji bahwa Anda mencoba memahami berbagai hal, alih-alih hanya mengajukan pertanyaan pada help desk, yang merupakan hal yang sebagian besar kami dapatkan di sini. Masing-masing pertanyaan ini pantas mendapat jawaban panjang sendiri. Saya sarankan setidaknya memecah posting Anda menjadi bagian-bagian yang jelas, dan menempatkan masing-masing bagian dalam pertanyaan terpisah, sehingga menciptakan serangkaian pertanyaan.
Faheem Mitha
Kemudian Anda dapat memposting pertanyaan-pertanyaan ini bersama atau berurutan. Tidak apa-apa, saya pikir, jika Anda merujuk pertanyaan lain (atau pertanyaan) dalam sebuah pertanyaan.
Faheem Mitha
1
Jika Anda ingin kiat membersihkan pertanyaan Anda, saya sarankan Anda masuk ke ruang obrolan dan berbicara dengan orang-orang di sana. Kami sudah membicarakannya di sini. :-)
Faheem Mitha
Banyak terima kasih atas komentarnya, @FaheemMitha - Saya juga memiliki keraguan yang sama, tetapi saya tidak benar-benar yakin bagaimana memotong pertanyaan - dan tidak sadar sampai sekarang saya dapat menggunakan obrolan untuk itu (dan saya tidak tertarik pada menggunakan meta untuk bertanya tentang nasihat semacam itu); pasti akan mencoba obrolan lain kali. Untungnya, kali ini berhasil dengan jawaban yang sangat bisa diterima ... Ceria!
sdaau
@ Saauau, apakah Anda mengetahui cara memonitor akses disk?
ransh

Jawaban:

10

Anda terlalu banyak bertanya dalam satu pertanyaan — yah, secara teknis tidak, karena saya kira "apakah pemahaman ini benar" dapat dijawab dengan cepat: tidak. Tapi itu bukan jawaban yang berguna.

Pertama, Anda benar ata_piixdan sd_modtampaknya sedang dikompilasi ke kernel Anda. Itu adalah pilihan yang Anda buat untuk mengkonfigurasi kernel — Anda dapat mengabaikannya, memasukkannya, atau memasukkannya sebagai modul. (Sama dengan ext4).

Kedua, Anda menganggap menulis jauh lebih sederhana dari yang sebenarnya. Garis besar dasar cara kerja penulisan adalah bahwa kode sistem file menempatkan data untuk ditulis dalam memori, sebagai bagian dari buffer-cache, dan menandainya sebagai kebutuhan-untuk-ditulis ("kotor"). (Kecuali jika sudah terlalu banyak dalam RAM, dalam hal ini sebenarnya terpaksa melakukan tulis ...)

Kemudian, berbagai hal (seperti bdflushutas kernel) benar-benar membersihkan halaman yang kotor ke disk. Ini adalah ketika Anda akan melihat panggilan melalui sd, scsi, libata, ata_piix, io schedulers, PCI, dll. Meskipun ada kemungkinan DMA terlibat dalam write-out itu, itu adalah data yang akan ditransfer, dan mungkin perintah. Tetapi penulisan disk, setidaknya dalam SATA, ditangani dengan mengirim perintah yang pada dasarnya berarti "tulis sektor X dengan data Y". Tapi itu pasti tidak ditangani oleh pemetaan memori seluruh disk (pertimbangkan: Anda dapat menggunakan disk yang jauh lebih besar dari 4GiB pada mesin 32-bit).

Caching ditangani oleh subsistem manajemen memori (bukan driver), dalam hubungannya dengan sistem file, lapisan blok, dll.

tmpfsspesial, pada dasarnya sepenuhnya cache. Cache khusus yang tidak pernah dibuang atau ditulis kembali (meskipun dapat ditukar). Anda dapat menemukan kode di mm/shmem.cdan beberapa tempat lain (coba ack-grep --cc CONFIG_TMPFStemukan).

Pada dasarnya, menulis ke disk melewati sebagian besar subsistem kernel; jaringan adalah satu-satunya yang saya pikir tidak terlibat dalam contoh Anda. Menjelaskannya dengan benar membutuhkan upaya sepanjang buku; Saya sarankan mencari satu.

derobert
sumber
Hai @derobert - banyak, banyak terima kasih atas jawaban Anda; itu berisi jenis informasi persis yang saya lewatkan! Saya awalnya mulai dengan mencari ilustrasi sederhana ruang pengguna vs kernel, tetapi saya segera menyadari bahwa penulisan hard disk bukanlah sesuatu yang saya pahami sepenuhnya, dan bukankah itu sepele - terima kasih karena telah mengonfirmasi itu sebenarnya adalah sebuah buku usaha panjang! Bersulang!
sdaau
Sebuah catatan kecil: beberapa penjelasan dalam jawaban ini (mis. sudo bash...Pembilasan halaman kotor) dapat diamati, jika dalam skrip dalam OP: memori ftrace ditingkatkan ( echo 8192 > $KDBGPATH/buffer_size_kb); dan sync ;ditambahkan setelah ./wtest ;panggilan. Lalu saya bisa melihat flush-8, kworker( kthreadddi bawah dalam ps axf), dan syncitu sendiri, sebagai proses dalam ftracememanggil fungsi seperti misalnya ata_bmdma_setup()(yang merupakan bagian dari libata, yang ata_piixdibangun di atas), atau get_nr_dirty_inodes().
sdaau
4

Jadi pertanyaan pertama saya adalah - mengapa saya tidak dapat mengamati modul ata_piix di sini, hanya di log waktu boot? Apakah karena ata_piix (dan sd) dibangun sebagai driver bawaan di kernel (monolitik), dan bukannya dibangun sebagai modul kernel .ko (yang dapat dimuat)?

Anda tidak perlu menebak konfigurasi Anda. Di mesin saya, saya punya

$ uname -a
Linux orwell 3.2.0-4-amd64 #1 SMP Debian 3.2.51-1 x86_64 GNU/Linux

File konfigurasi untuk kernel ini terletak di /boot/config-3.2.0-4-amd64.

Anda bertanya tentang ata_piix. Mencari .configfile di atas , kita lihat CONFIG_ATA_PIIX=m. kami dapat mengkonfirmasi ini dengan melakukan

dlocate ata_piix.ko   

kalau tidak

dpkg -S ata_piix.ko

linux-image-3.2.0-4-amd64: /lib/modules/3.2.0-4-amd64/kernel/drivers/ata/ata_piix.ko

Jadi setidaknya di kernel saya, ini adalah modul.

Faheem Mitha
sumber
Terima kasih banyak untuk itu, @FaheemMitha - walaupun saya pernah mendengar (dan menggunakan) file konfigurasi sebelumnya, untuk beberapa alasan saya benar-benar lupa tentang hal itu dalam contoh ini; terlihat bagus! :)Pada sistem saya, grep ATA_PIIX /boot/config-2.6.38-16-generickata CONFIG_ATA_PIIX=y, yang mungkin berarti pada kernel ini, ata_piixadalah membangun "in-kernel", dan bukan sebagai modul. Bersulang!
sdaau