Zadanie 2: bufor zapisów¶
Data ogłoszenia: 31.03.2020
Termin oddania: 05.05.2020 (ostateczny 19.05.2020)
Materiały dodatkowe¶
Wprowadzenie¶
Syscall write
jest starym i dobrze przyjętym narzędziem do modyfikacji
plików. Ma jednak poważny problem: gdy program zacznie modyfikować plik
i napotka błąd na którymś etapie, nie jest w stanie łatwo przywrócić
pliku do stanu początkowego, powodując istnienie częściowo zmodyfikowanego
pliku.
Zadanie¶
Napisać modyfikację do jądra pozwalającą na cofnięcie zmian wykonanych
przez write
(a właściwie na buforowanie ich i zaaplikowanie na właściwy
plik dopiero, gdy poprosi o to użytkownik).
Dodać do flag syscalla open
nową flagę O_BUFFERED_WRITE
(o wartośći
040000000
), która
spowoduje buforowanie zapisów przed zaaplikowaniem ich na właściwy plik.
W przypadku zapisu do deskryptora pliku otwartego z taką flagą, zapis nie powinien być przesyłany do warstwy systemu plików — zamiast tego, zapisane dane powinny być magazynowane w buforze prywatnym dla danego deskryptora, by mogły być później zaaplikowane.
Za zapis uznajemy wykonanie syscalli modyfikujących plik: ftruncate
,
write
, pwrite
, writev
, pwritev
, pwritev2
.
Odczyt na naszym deskryptorze pliku powinien pokazywać buforowane zmiany. Zmiany nie powinny być jednak widoczne (do momentu zatwierdzenia) przez jakiekolwiek inne otwarte deskryptory wskazujące na ten sam plik.
Zmodyfikować syscall fsync
tak, aby wykonanie go na buforowanym
deskryptorze pliku powodowało zatwierdzenie wszystkich buforowanych
obecnie zmian (zaaplikowanie ich do pliku na dysku).
W przypadku zamknięcia deskryptora pliku z włączonym buforowaniem bez
wywołania fsync
, należy wyrzucić wszystkie buforowane
zmiany.
Nie trzeba wspierać w zadaniu funkcji mmap
— próba zamapowania pliku
otwartego w ten sposób powinna się skończyć błędem. Nie trzeba też wspierać
vmsplice
, splice
, tee
, sendfile
.
Nie trzeba wspierać kombinacji O_APPEND
z O_BUFFERED_WRITE
.
Założenia interakcji z innymi użytkownikami¶
W naszym deskryptorze powinniśmy pamiętać tylko faktycznie zmodyfikowane
zakresy danych — zaaplikowanie zmian nie powinno zmienić żadnych danych
w pliku poza obszarami zmienionymi przez write
na naszym deskryptorze,
nawet jeśli plik był równolegle zmieniany przez innych użytkowników.
W szczególności, gdy dwóch różnych użytkowników otworzy ten sam plik
w trybie buforowania i będzie równolegle wprowadzać zmiany w rozłącznych
obszarach, po czym wywoła fsync
, ostateczny stan pliku powinien
uwzględniać zmiany obydwu użytkowników.
Może się zdarzyć, że zaaplikowanie zmian okaże się niemożliwe, gdy plik
w międzyczasie zostanie skrócony (ftruncate
) — w takim wypadku, fsync
powinien zwrócić błąd.
Zasady oceniania¶
Za zadanie można uzyskać do 10 punktów. Na ocenę zadania składają się dwie części:
wynik testów (od 0 do 10 punktów)
ocena kodu rozwiązania (od 0 do -10 punktów)
Najczęstsze błędy - spis oznaczeń w USOSwebie¶
Bezpośredni dostęp do pamięci userspace(np memcpy zamiast copy_*_user) (-0.5, max 3szt.)
Brak sprawdzania wyniku alokacji pamiąci lub nieprawidłowa obsługa błędu (-0.5, max 3 szt.)
Wyciek pamięci: brak kfree w obsłudze błędu (-0.2, max 3 szt.)
Include pliku C zamiast dodanie go do systemu budowania (-0.2)
Przekazywanie adresu z kernela do funkcji przyjmującej typ
__user
(-0.5, -0.0 przy jednoczesnym wystąpienu z #1)Wyciek: brak zwalniania struktur przy close (bez fsync) (-0.2)
Zwracanie nieprawidłowo zakodowanych błedów (
ENOMEM
zamiast-ENOMEM
) (-0.2)Zwracanie
-EFAULT
zamiast-ENOMEM
przy braku pamięci (-0.2)Brak zwracania
-EFAULT
przy błędzie wcopy_*_user
(-0.5)Brak błędu przy wywołaniu
mmap
(-0.2)Błędy / deadlock przy wielu wątkach (-0.5)
Brak poprawnej obsługi dużych (większych niż maksymalna alokacja
kmalloc
) zapisów / odczytów (-0.5)
Forma rozwiązania¶
Jako rozwiązanie należy wysłać paczkę zawierającą:
patcha na jądro w wersji 5.5.5, w jednym z następujących formatów:
patch wygenerowaniy przez diffa z opcjami
-uprN
nakładający się przezpatch -p1
git format-patch
krótki opis rozwiązania
Rozwiązania prosimy nadsyłać na adres p.zuk@mimuw.edu.pl
z kopią
do mwk@mimuw.edu.pl
.
Wskazówki¶
Aby proces przy odczytach poprawnie widział buforowane dane, należy przechwycić:
read
,pread
,readv
,preadv
,preadv2
sprawdzenie rozmiaru pliku przez
fstat
lseek
z opcjąSEEK_END