C'è già una grande serie di risposte a questo su Stack Overflow e Server Fault, ma mancavano alcune tecniche. Per semplificarti la vita, ecco un elenco di meccanismi di iniezione di guasti I/O per VM/dispositivo a blocchi Linux/file system Linux/libreria spazio utente Linux:
- Utilizzare i dispositivi error/flakey/delay/dm-dust di Device Mapper per restituire errori/corruzione da, o ritardare/dividere l'IO a un dispositivo a blocchi sintetizzato (kernel, richiede che il kernel sia stato creato con il supporto del device mapper, dispositivo aggiuntivo appropriato moduli mapper (dm-dust è disponibile solo su kernel>=5.2) e per avere i bit dello spazio utente del device mapper).
- Usa la personalità difettosa di md per eseguire l'iniezione periodica di guasti su un dispositivo a blocchi sintetizzato. Vedi il
--layout
opzione della pagina man mdadm per come configurarlo (kernel e mdadm userspace bit). - Utilizza libfiu per eseguire l'iniezione di errore sulle chiamate API POSIX (spazio utente, può essere utilizzato con
LD_PRELOAD
). - Utilizza l'iniettore di errori del kernel Linux per iniettare un errore nel dispositivo a blocchi sottostante (kernel, richiede che il kernel sia stato compilato con
FAIL_MAKE_REQUEST=y
). - Utilizzo di SystemTap per eseguire l'iniezione di errori (kernel, richiede che un kernel sia stato compilato con molte cose).
- Inietta errori del filesystem utilizzando CharybdeFS o PetardFS (spazio utente tramite FUSE).
- Crea un dispositivo a blocchi sintetizzato utilizzando il driver scsi_debug di Linux che esegue l'iniezione di errori (kernel).
- Esegui il tuo sistema all'interno di QEMU e utilizza QEMU per iniettare errori del dispositivo a blocchi utilizzando il driver blkdebug (VM).
- Crea un dispositivo a blocchi sintetizzato tramite le opzioni del dispositivo null_blk per iniettare errori (kernel>=4.14 ma opzioni come le probabilità di timeout non sono arrivate fino alla 4.17 e richiedono che il kernel sia stato compilato con
BLK_DEV_NULL_BLK_FAULT_INJECTION=y
). - Crea un dispositivo di blocco di rete sintetizzato che viene servito all'host tramite i filtri NBDkit come
delay
oerror
e quindi collegarvi un dispositivo a blocchi tramitenbd-client
(kernel + bit dello spazio utente NBD, kernel>=4.18 compilato con supporto NBD, nbdclient>=3.18 e nbdkit>=1.8.1 consigliati - guarda il video dimostrativo di NBDKit intorno ai 20 minuti).
Fatto positivo:SQLite ha un driver VFS per la simulazione degli errori in modo che possa ottenere una buona copertura del test.
Correlati:
- Come posso simulare un disco guasto durante il test?
- Simulare un dispositivo a blocchi difettoso con errori di lettura?
- Genera un errore di lettura
- Provocare intenzionalmente un errore di I/O in Linux?
Puoi usare dmsetup
per creare un dispositivo device-mapper usando il error
o flakey
obiettivi per simulare i guasti.
dmsetup create test --table '0 123 flakey 1 0 /dev/loop0'
Dove 123 è la lunghezza del dispositivo, in settori e /dev/loop0 è il dispositivo originale su cui vuoi simulare gli errori. Per errore, non hai bisogno degli argomenti successivi in quanto restituisce sempre un errore.
Vuoi un meccanismo di iniezione dei guasti per I/O.
Su Linux, ecco un metodo che non richiede alcuna configurazione precedente e genera un errore insolito (non EIO "Input/output error" ma ESRCH "No such process"):
cat /proc/1234/mem
dove 1234 è il PID di un processo in esecuzione come lo stesso utente del processo che stai testando, ma non quel processo stesso. Ringraziamenti a rubasov per aver pensato a /proc/$pid/mem
.
Se usi il PID del processo stesso, ottieni EIO, ma solo se stai leggendo da un'area che non è mappata nella memoria del processo. La prima pagina non viene mai mappata, quindi va bene se leggi il file in sequenza, ma non è adatto per un processo di database che cerca direttamente al centro del file.
Con un po' di configurazione in più come root, puoi sfruttare il device mapper per creare file con settori validi e settori danneggiati.
Un altro approccio sarebbe quello di implementare un piccolo filesystem FUSE. EIO è il codice di errore predefinito quando il driver del file system dello spazio utente fa qualcosa di sbagliato, quindi è facile da ottenere. Entrambi i collegamenti Perl e Python vengono forniti con esempi per iniziare, puoi scrivere rapidamente un filesystem che rispecchia principalmente i file esistenti ma inietta un EIO in luoghi scelti con cura. Esiste un filesystem di questo tipo:petardfs (articolo), non so quanto funzioni bene fuori dagli schemi.
Ancora un altro metodo è un LD_PRELOAD
involucro. Uno esistente è Libfiu (fault injection in userspace). Funziona precaricando una libreria che sovraccarica le chiamate API POSIX. Puoi scrivere semplici direttive o codice C arbitrario per sovrascrivere il normale comportamento.