TL; DR: ถ้าเคอร์เนล Linux สูญเสียการเขียน I / O ที่บัฟเฟอร์แล้วมีวิธีใดบ้างที่แอปพลิเคชันจะค้นหา?
ฉันรู้ว่าคุณต้องfsync()
แฟ้ม (และไดเรกทอรีแม่ของมัน) เพื่อความทนทาน คำถามคือหากเคอร์เนลสูญเสียบัฟเฟอร์สกปรกที่รอการเขียนเนื่องจากข้อผิดพลาด I / O แอปพลิเคชันสามารถตรวจพบสิ่งนี้และกู้คืนหรือยกเลิก?
คิดว่าแอ็พพลิเคชันฐานข้อมูล ฯลฯ ที่ลำดับการเขียนและความทนทานในการเขียนมีความสำคัญ
เขียนหายไป? อย่างไร?
ลินุกซ์เคอร์เนลสามารถป้องกันชั้นภายใต้สถานการณ์บางแพ้บัฟเฟอร์การร้องขอ I / O ที่ได้รับการส่งเรียบร้อยแล้วโดยwrite()
, pwrite()
ฯลฯ ด้วยข้อผิดพลาดเช่น:
Buffer I/O error on device dm-0, logical block 12345
lost page write due to I/O error on dm-0
(ดูend_buffer_write_sync(...)
และend_buffer_async_write(...)
ในfs/buffer.c
)
ในเมล็ดที่ใหม่กว่าข้อผิดพลาดจะมี "การหายไปของ async page write"แทนเช่น:
Buffer I/O error on dev dm-0, logical block 12345, lost async page write
เนื่องจากแอปพลิเคชันwrite()
จะส่งคืนโดยไม่มีข้อผิดพลาดดูเหมือนจะไม่มีวิธีรายงานข้อผิดพลาดกลับไปที่แอปพลิเคชัน
กำลังตรวจจับพวกเขาหรือ
ฉันไม่คุ้นเคยกับที่มาของเคอร์เนล แต่ฉันคิดว่ามันตั้งAS_EIO
อยู่บนบัฟเฟอร์ที่ล้มเหลวที่จะถูกตัดออกถ้ามันทำการเขียนแบบ async:
set_bit(AS_EIO, &page->mapping->flags);
set_buffer_write_io_error(bh);
clear_buffer_uptodate(bh);
SetPageError(page);
แต่มันก็ไม่ชัดเจนสำหรับฉันว่าแอปพลิเคชันสามารถค้นหาข้อมูลเกี่ยวกับเรื่องนี้ได้อย่างไรในภายหลังเมื่อมันfsync()
เป็นไฟล์เพื่อยืนยันว่ามันอยู่ในดิสก์
ดูเหมือนว่าwait_on_page_writeback_range(...)
ในmm/filemap.c
ยุทธโดยdo_sync_mapping_range(...)
ในfs/sync.c
sys_sync_file_range(...)
ซึ่งเป็นเลี้ยวเรียกได้ว่า มันจะส่งคืน-EIO
หากไม่สามารถเขียนบัฟเฟอร์อย่างน้อยหนึ่งบัฟเฟอร์
หากตามที่ฉันคาดเดาสิ่งนี้จะแพร่กระจายไปสู่fsync()
ผลลัพธ์ของมันหากแอปพลิเคชันตื่นตระหนกและพบว่าเกิดข้อผิดพลาด I / O จากfsync()
และรู้วิธีการทำงานของมันอีกครั้งเมื่อรีสตาร์ทนั่นควรจะป้องกันอย่างเพียงพอหรือไม่
มีสันนิษฐานว่าวิธีการที่แอปรู้ว่าไม่มีซึ่งไบต์ชดเชยในสอดคล้องไฟล์ไปยังหน้าหายไปดังนั้นจึงสามารถเขียนพวกเขาถ้ามันรู้วิธี แต่ถ้าแอปซ้ำการทำงานทั้งหมดที่ค้างอยู่ตั้งแต่ช่วงที่ประสบความสำเร็จfsync()
ของไฟล์และเขียนใหม่ว่า บัฟเฟอร์เคอร์เนลสกปรกใด ๆ ที่สอดคล้องกับการเขียนที่หายไปกับไฟล์ซึ่งควรล้างการตั้งค่าสถานะข้อผิดพลาด I / O ใด ๆ บนเพจที่สูญหายและอนุญาตให้ทำรายการถัดfsync()
ไปจนเสร็จสมบูรณ์ใช่ไหม
มีสถานการณ์อื่นใดที่ไม่เป็นอันตรายซึ่งfsync()
อาจกลับมาอีก-EIO
เมื่อการประกันตัวออกไปและการทำซ้ำจะรุนแรงเกินไปหรือไม่?
ทำไม?
แน่นอนข้อผิดพลาดดังกล่าวไม่ควรเกิดขึ้น ในกรณีนี้ข้อผิดพลาดเกิดขึ้นจากการโต้ตอบที่โชคร้ายระหว่างdm-multipath
ค่าเริ่มต้นของไดรเวอร์และรหัสการรับรู้ที่ SAN ใช้เพื่อรายงานความล้มเหลวในการจัดสรรพื้นที่เก็บข้อมูลแบบ thin-provisioned แต่นี่ไม่ใช่เหตุการณ์เดียวที่พวกเขาสามารถเกิดขึ้นได้ฉันได้เห็นรายงานของมันจาก LVM แบบบางที่จัดเตรียมไว้เช่นที่ใช้โดย libvirt, Docker และอีกมากมาย แอปพลิเคชันที่สำคัญเช่นฐานข้อมูลควรพยายามจัดการกับข้อผิดพลาดดังกล่าวแทนที่จะดำเนินการอย่างสุ่มสี่สุ่มห้าราวกับว่าทั้งหมดนั้นดี
ถ้าเคอร์เนลคิดว่ามันโอเคที่จะสูญเสียการเขียนโดยไม่ต้องตายด้วยความตื่นตระหนกของเคอร์เนลแอปพลิเคชันต้องหาวิธีรับมือ
ผลกระทบในทางปฏิบัติคือฉันพบกรณีที่ปัญหา multipath กับ SAN ทำให้เกิดการเขียนที่หายไปซึ่งทำให้เกิดความเสียหายของฐานข้อมูลเนื่องจาก DBMS ไม่ทราบว่าการเขียนล้มเหลว ไม่สนุก.