Kernel: Avoid double-locking devices when trying to acquire them

Previously, you'd occasionally see this sort of construct (simplified):
```
return FooDevice::all_instances().with([&](auto& list) {
    for (auto& device : list) {
        if (/* search condition */)
            continue;
        return do_something_that_reacquires(device.index());
    }
    return ENOENT;
});
```

This would only work if the relevant `all_instances()` used a recursive
spinlock, since reacquiring the device would lock that again.

To get around this, a new helper has been added in `Device` through
which devices can be accessed whilst locking the device list, removing
the need to loop through the device type's `all_instances()`.
This commit is contained in:
implicitfield
2025-05-16 14:12:16 +03:00
committed by Sönke Holz
parent d3a314f5cd
commit 6a4ceb6bf2
12 changed files with 74 additions and 59 deletions

View File

@@ -17,9 +17,9 @@ static InodeIndex loop_index_to_inode_index(unsigned loop_index)
return loop_index + 2;
}
DevLoopFSInode::DevLoopFSInode(DevLoopFS& fs, InodeIndex index, LoopDevice& loop_device)
DevLoopFSInode::DevLoopFSInode(DevLoopFS& fs, InodeIndex index, LockWeakPtr<LoopDevice> loop_device)
: Inode(fs, index)
, m_loop_device(loop_device)
, m_loop_device(move(loop_device))
{
}
@@ -76,14 +76,7 @@ ErrorOr<NonnullRefPtr<Inode>> DevLoopFSInode::lookup(StringView name)
if (!loop_index.has_value())
return ENOENT;
return LoopDevice::all_instances().with([&](auto& list) -> ErrorOr<NonnullRefPtr<Inode>> {
for (LoopDevice& loop_device : list) {
if (loop_device.index() != loop_index.value())
continue;
return fs().get_inode({ fsid(), loop_index_to_inode_index(loop_index.value()) });
}
return ENOENT;
});
return fs().get_inode({ fsid(), loop_index_to_inode_index(loop_index.value()) });
}
ErrorOr<void> DevLoopFSInode::flush_metadata()