8#include "pedigree/kernel/Log.h"
9#include "pedigree/kernel/TargetInfo.h"
10#include "pedigree/kernel/machine/Disk.h"
11#include "pedigree/kernel/utilities/Cache.h"
12#include "pedigree/kernel/utilities/utility.h"
16constexpr size_t TerminalBytes = 512;
17static_assert(PageSize >= TerminalBytes,
"disk regression requires one sector per target page");
19bool cacheRangeGeometry() {
20 constexpr uintptr_t EditingKey = 0x57A6000;
21 constexpr uintptr_t PublishedKey = EditingKey + (4 * PageSize);
24 bool alreadyExisted =
true;
25 const uintptr_t invalid = cache.insert(EditingKey, PageSize + TerminalBytes, &alreadyExisted);
26 const bool insertionRejected = !invalid && !alreadyExisted && !cache.exists(EditingKey, PageSize);
28 const uintptr_t editing = cache.insert(EditingKey);
29 cache.markNoLongerEditing(EditingKey, PageSize + TerminalBytes);
30 const bool invalidPublishLeftEditing = editing && cache.discardEditing(EditingKey);
32 const uintptr_t published = cache.insert(PublishedKey);
33 cache.markNoLongerEditing(PublishedKey);
34 cache.markEditing(PublishedKey, PageSize + TerminalBytes);
35 const bool invalidEditLeftPublished = published && !cache.discardEditing(PublishedKey);
38 const bool passed = insertionRejected && invalidPublishLeftEditing && invalidEditLeftPublished;
40 NOTICE(
"HOSTED-WAIT-TEST: PASS cache-range-geometry");
43 "HOSTED-WAIT-TEST: FAIL cache-range-geometry: a partial cache range "
44 "changed cache state");
49class SequenceDisk final :
public Disk {
51 static constexpr size_t DataSize = (2 * PageSize) + TerminalBytes;
53 SequenceDisk() : m_Data(new uint8_t[DataSize]), m_BalanceError(false) {
54 for (
size_t i = 0; i < DataSize; ++i) {
55 m_Data[i] =
static_cast<uint8_t
>((i * 31) ^ (i >> 3));
57 ByteSet(m_References, 0,
sizeof(m_References));
60 ~SequenceDisk()
override {
65 if (location >= DataSize) {
69 const uint64_t page = location - (location % PageSize);
70 const size_t offset = location - page;
71 const size_t validLength = PageSize < (DataSize - page) ? PageSize : (DataSize - page);
72 ++m_References[page / PageSize];
73 return BufferView(m_Data + location, validLength - offset);
76 size_t getSize()
const override {
84 bool pin(uint64_t location)
override {
85 if (location >= DataSize) {
88 ++m_References[location / PageSize];
92 void unpin(uint64_t location)
override {
93 if (location >= DataSize || !m_References[location / PageSize]) {
94 m_BalanceError =
true;
97 --m_References[location / PageSize];
100 const uint8_t* data()
const {
104 bool balanced()
const {
105 return !m_BalanceError && !m_References[0] && !m_References[1] && !m_References[2];
110 size_t m_References[3];
114bool diskViewSequencePageSpan() {
115 constexpr size_t ReadLength = 2 * PageSize;
119 uint8_t* copied =
new uint8_t[ReadLength];
121 const bool read = disk.readViews(TerminalBytes, ReadLength, views);
122 const bool geometry = read && views.count() == 3 &&
123 views[0].size() == (PageSize - TerminalBytes) &&
124 views[1].size() == PageSize && views[2].size() == TerminalBytes;
125 const bool copiedAll = geometry && views.copyTo(copied, ReadLength) &&
126 !MemoryCompare(copied, disk.data() + TerminalBytes, ReadLength);
128 disk.unpinViews(TerminalBytes, views);
130 const bool released = disk.balanced() && views.empty();
134 const bool capacityFailure = !disk.readViews(TerminalBytes, ReadLength, shortViews) &&
135 shortViews.empty() && disk.balanced();
138 const bool passed = copiedAll && released && capacityFailure;
140 NOTICE(
"HOSTED-WAIT-TEST: PASS disk-view-sequence-page-span");
143 "HOSTED-WAIT-TEST: FAIL disk-view-sequence-page-span: a multi-page "
144 "read lost bounds or cache ownership");
150bool runHostedStoragePageRegressions() {
151 return cacheRangeGeometry() && diskViewSequencePageSpan();
virtual BufferView read(uint64_t location)
virtual size_t getSize() const
Gets the size of the disk.
virtual void unpin(uint64_t location)=0
virtual MUST_USE_RESULT bool pin(uint64_t location)=0
Pins a cache page.
virtual size_t getBlockSize() const
Gets the preferred I/O extent of the disk.
static constexpr size_t getPageSize() noexcept