mirror of
https://github.com/SerenityOS/serenity.git
synced 2025-01-24 02:12:09 -05:00
IDEDiskDevice: Detect disk errors and report failure to clients.
Previously we'd just fail silently if there was an I/O error of any kind.
This commit is contained in:
parent
e6de6c4f45
commit
298a49c688
3 changed files with 31 additions and 16 deletions
|
@ -29,8 +29,10 @@ Ext2FS::~Ext2FS()
|
||||||
ByteBuffer Ext2FS::read_super_block() const
|
ByteBuffer Ext2FS::read_super_block() const
|
||||||
{
|
{
|
||||||
auto buffer = ByteBuffer::create_uninitialized(1024);
|
auto buffer = ByteBuffer::create_uninitialized(1024);
|
||||||
device().read_block(2, buffer.pointer());
|
bool success = device().read_block(2, buffer.pointer());
|
||||||
device().read_block(3, buffer.offset_pointer(512));
|
ASSERT(success);
|
||||||
|
success = device().read_block(3, buffer.offset_pointer(512));
|
||||||
|
ASSERT(success);
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,7 +222,8 @@ bool Ext2FS::write_block_list_for_inode(InodeIndex inode_index, ext2_inode& e2in
|
||||||
--remaining_blocks;
|
--remaining_blocks;
|
||||||
}
|
}
|
||||||
stream.fill_to_end(0);
|
stream.fill_to_end(0);
|
||||||
write_block(e2inode.i_block[EXT2_IND_BLOCK], block_contents);
|
bool success = write_block(e2inode.i_block[EXT2_IND_BLOCK], block_contents);
|
||||||
|
ASSERT(success);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!remaining_blocks)
|
if (!remaining_blocks)
|
||||||
|
@ -540,6 +543,7 @@ ssize_t Ext2FSInode::write_bytes(off_t offset, size_t count, const byte* data, F
|
||||||
bool success = fs().write_block(block_list[bi], block);
|
bool success = fs().write_block(block_list[bi], block);
|
||||||
if (!success) {
|
if (!success) {
|
||||||
kprintf("Ext2FSInode::write_bytes: write_block(%u) failed (lbi: %u)\n", block_list[bi], bi);
|
kprintf("Ext2FSInode::write_bytes: write_block(%u) failed (lbi: %u)\n", block_list[bi], bi);
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
remaining_count -= num_bytes_to_copy;
|
remaining_count -= num_bytes_to_copy;
|
||||||
|
@ -826,8 +830,9 @@ bool Ext2FS::write_ext2_inode(unsigned inode, const ext2_inode& e2inode)
|
||||||
if (!block)
|
if (!block)
|
||||||
return false;
|
return false;
|
||||||
memcpy(reinterpret_cast<ext2_inode*>(block.offset_pointer(offset)), &e2inode, inode_size());
|
memcpy(reinterpret_cast<ext2_inode*>(block.offset_pointer(offset)), &e2inode, inode_size());
|
||||||
write_block(block_index, block);
|
bool success = write_block(block_index, block);
|
||||||
return true;
|
ASSERT(success);
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector<Ext2FS::BlockIndex> Ext2FS::allocate_blocks(unsigned group, unsigned count)
|
Vector<Ext2FS::BlockIndex> Ext2FS::allocate_blocks(unsigned group, unsigned count)
|
||||||
|
@ -956,7 +961,8 @@ bool Ext2FS::set_inode_allocation_state(unsigned index, bool newState)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
bitmap.set(bit_index, newState);
|
bitmap.set(bit_index, newState);
|
||||||
write_block(bgd.bg_inode_bitmap + bitmap_block_index, block);
|
bool success = write_block(bgd.bg_inode_bitmap + bitmap_block_index, block);
|
||||||
|
ASSERT(success);
|
||||||
|
|
||||||
// Update superblock
|
// Update superblock
|
||||||
auto& sb = *reinterpret_cast<ext2_super_block*>(m_cached_super_block.pointer());
|
auto& sb = *reinterpret_cast<ext2_super_block*>(m_cached_super_block.pointer());
|
||||||
|
@ -998,7 +1004,8 @@ bool Ext2FS::set_block_allocation_state(GroupIndex group, BlockIndex bi, bool ne
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
bitmap.set(bit_index, new_state);
|
bitmap.set(bit_index, new_state);
|
||||||
write_block(bgd.bg_block_bitmap + bitmap_block_index, block);
|
bool success = write_block(bgd.bg_block_bitmap + bitmap_block_index, block);
|
||||||
|
ASSERT(success);
|
||||||
|
|
||||||
// Update superblock
|
// Update superblock
|
||||||
auto& sb = *reinterpret_cast<ext2_super_block*>(m_cached_super_block.pointer());
|
auto& sb = *reinterpret_cast<ext2_super_block*>(m_cached_super_block.pointer());
|
||||||
|
|
|
@ -60,17 +60,14 @@ unsigned IDEDiskDevice::block_size() const
|
||||||
|
|
||||||
bool IDEDiskDevice::read_block(unsigned index, byte* out) const
|
bool IDEDiskDevice::read_block(unsigned index, byte* out) const
|
||||||
{
|
{
|
||||||
const_cast<IDEDiskDevice&>(*this).read_sectors(index, 1, out);
|
return const_cast<IDEDiskDevice&>(*this).read_sectors(index, 1, out);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IDEDiskDevice::write_block(unsigned index, const byte* data)
|
bool IDEDiskDevice::write_block(unsigned index, const byte* data)
|
||||||
{
|
{
|
||||||
write_sectors(index, 1, data);
|
return write_sectors(index, 1, data);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DISK_DEBUG
|
|
||||||
static void print_ide_status(byte status)
|
static void print_ide_status(byte status)
|
||||||
{
|
{
|
||||||
kprintf("DRQ=%u BUSY=%u DRDY=%u SRV=%u DF=%u CORR=%u IDX=%u ERR=%u\n",
|
kprintf("DRQ=%u BUSY=%u DRDY=%u SRV=%u DF=%u CORR=%u IDX=%u ERR=%u\n",
|
||||||
|
@ -83,7 +80,6 @@ static void print_ide_status(byte status)
|
||||||
(status & IDX) != 0,
|
(status & IDX) != 0,
|
||||||
(status & ERR) != 0);
|
(status & ERR) != 0);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
bool IDEDiskDevice::wait_for_irq()
|
bool IDEDiskDevice::wait_for_irq()
|
||||||
{
|
{
|
||||||
|
@ -98,13 +94,21 @@ bool IDEDiskDevice::wait_for_irq()
|
||||||
#ifdef DISK_DEBUG
|
#ifdef DISK_DEBUG
|
||||||
kprintf("disk: got interrupt!\n");
|
kprintf("disk: got interrupt!\n");
|
||||||
#endif
|
#endif
|
||||||
|
memory_barrier();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IDEDiskDevice::handle_irq()
|
void IDEDiskDevice::handle_irq()
|
||||||
{
|
{
|
||||||
#ifdef DISK_DEBUG
|
|
||||||
byte status = IO::in8(0x1f7);
|
byte status = IO::in8(0x1f7);
|
||||||
|
if (status & ERR) {
|
||||||
|
print_ide_status(status);
|
||||||
|
m_device_error = IO::in8(0x1f1);
|
||||||
|
kprintf("IDEDiskDevice: Error %b!\n", m_device_error);
|
||||||
|
} else {
|
||||||
|
m_device_error = 0;
|
||||||
|
}
|
||||||
|
#ifdef DISK_DEBUG
|
||||||
kprintf("disk:interrupt: DRQ=%u BUSY=%u DRDY=%u\n", (status & DRQ) != 0, (status & BUSY) != 0, (status & DRDY) != 0);
|
kprintf("disk:interrupt: DRQ=%u BUSY=%u DRDY=%u\n", (status & DRQ) != 0, (status & BUSY) != 0, (status & DRDY) != 0);
|
||||||
#endif
|
#endif
|
||||||
m_interrupted = true;
|
m_interrupted = true;
|
||||||
|
@ -206,6 +210,9 @@ bool IDEDiskDevice::read_sectors(dword start_sector, word count, byte* outbuf)
|
||||||
enable_irq();
|
enable_irq();
|
||||||
wait_for_irq();
|
wait_for_irq();
|
||||||
|
|
||||||
|
if (m_device_error)
|
||||||
|
return false;
|
||||||
|
|
||||||
byte status = IO::in8(0x1f7);
|
byte status = IO::in8(0x1f7);
|
||||||
if (status & DRQ) {
|
if (status & DRQ) {
|
||||||
#ifdef DISK_DEBUG
|
#ifdef DISK_DEBUG
|
||||||
|
@ -265,5 +272,5 @@ bool IDEDiskDevice::write_sectors(dword start_sector, word count, const byte* da
|
||||||
enable_irq();
|
enable_irq();
|
||||||
wait_for_irq();
|
wait_for_irq();
|
||||||
|
|
||||||
return true;
|
return !m_device_error;
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,8 @@ private:
|
||||||
word m_cylinders { 0 };
|
word m_cylinders { 0 };
|
||||||
word m_heads { 0 };
|
word m_heads { 0 };
|
||||||
word m_sectors_per_track { 0 };
|
word m_sectors_per_track { 0 };
|
||||||
mutable volatile bool m_interrupted { false };
|
volatile bool m_interrupted { false };
|
||||||
|
volatile byte m_device_error { 0 };
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue