20#include "pedigree/kernel/machine/Disk.h"
21#include "pedigree/kernel/process/TerminationDeferral.h"
22#include "pedigree/kernel/utilities/String.h"
24DiskReadView::DiskReadView()
25 : m_Owner(nullptr), m_Location(0), m_Data(nullptr), m_Size(0), m_Writable(false), m_Use() {}
27DiskReadView::DiskReadView(
Disk* owner, uint64_t location,
BufferView view,
bool writable,
31 m_Data(static_cast<const uint8_t*>(view.data())),
34 m_Use(static_cast<
DiskUse&&>(use)) {}
43 m_Owner = other.m_Owner;
44 m_Location = other.m_Location;
45 m_Data = other.m_Data;
46 m_Size = other.m_Size;
47 m_Writable = other.m_Writable;
48 m_Use =
static_cast<DiskUse&&
>(other.m_Use);
49 other.m_Owner =
nullptr;
50 other.m_Data =
nullptr;
56DiskReadView::~DiskReadView() {
63 view.m_Data =
static_cast<const uint8_t*
>(data);
69void DiskReadView::reset() {
72 m_Owner->releaseView(m_Location, m_Writable);
84Disk::Disk() : m_Endpoint(nullptr) {
85 m_SpecificType.assign(
"Generic Disk", 13);
94Disk* Disk::physicalDisk() {
98bool Disk::acquireUse(
DiskUse& use) {
99 Disk* physical = physicalDisk();
104 if (!physical->m_Endpoint) {
108 return DiskEndpoints::acquire(physical->m_Endpoint, physical, use);
111uint32_t Disk::endpointId() {
112 Disk* physical = physicalDisk();
113 return physical ? DiskEndpoints::id(physical->m_Endpoint, physical) : 0;
121bool Disk::getPartitionLabel(
String& label)
const {
126void Disk::reserveEndpoint() {
128 m_Endpoint = DiskEndpoints::reserve(
this);
130void Disk::publishEndpoint() {
131 DiskEndpoints::publish(m_Endpoint);
134 DiskEndpoints::retire(m_Endpoint,
this);
136bool Disk::tryCloseEndpoint() {
137 return DiskEndpoints::tryClose(m_Endpoint,
this);
139void Disk::reopenEndpoint() {
140 DiskEndpoints::reopen(m_Endpoint,
this);
144 return PagingStatus::Unsupported;
151Disk::SubType Disk::getSubType() {
156 str.assign(
"Generic disk", 13);
160 str.assign(
"Generic disk", 13);
170 if (!acquireUse(use))
172 uint64_t token = location;
173 const auto view = acquireView(location,
false, token);
181 if (!acquireUse(use))
183 uint64_t token = location;
184 const auto view = acquireView(location,
true, token);
188BufferView Disk::acquireView(uint64_t location,
bool writable, uint64_t& token) {
190 return read(location);
193void Disk::releaseView(uint64_t location,
bool writable) {
200 if (count > MaxReadBuffers || (count && !buffers))
202 for (
size_t i = 0; i < count; ++i)
203 buffers[i].complete =
false;
208 if (!acquireUse(diskUse))
211 for (
size_t i = 0; i < count; ++i) {
212 auto& request = buffers[i];
213 request.complete =
readInto(request.location, request.buffer, request.length);
214 success &= request.complete;
222 if (!acquireUse(diskUse))
224 if ((!buffer && length) || location >
getSize() || length >
getSize() - location)
229 auto* output =
static_cast<uint8_t*
>(buffer);
231 const uint64_t aligned = location - location % 512;
232 const size_t offset = location - aligned;
236 if (view.size() <= offset) {
239 const size_t available = view.size() - offset;
240 const size_t chunk = length < available ? length : available;
241 view.copyTo(output, chunk, offset);
249bool Disk::writeFrom(uint64_t location,
const void* buffer,
size_t length) {
252 if (!acquireUse(diskUse))
254 if ((!buffer && length) || location >
getSize() || length >
getSize() - location)
259 const auto* input =
static_cast<const uint8_t*
>(buffer);
261 const uint64_t aligned = location - location % 512;
262 const size_t offset = location - aligned;
266 if (view.size() <= offset) {
270 const size_t available = view.size() - offset;
271 const size_t chunk = length < available ? length : available;
272 MemoryCopy(view.subview(offset, chunk).data(), input, chunk);
274 const bool written =
sync(aligned,
false);
286 if (count > MaxWriteBuffers || (count && !buffers))
288 for (
size_t i = 0; i < count; ++i)
289 buffers[i].complete =
false;
290 bool succeeded =
true;
291 for (
size_t i = 0; i < count; ++i) {
292 auto& buffer = buffers[i];
293 buffer.complete = writeFrom(buffer.location, buffer.buffer, buffer.length);
294 succeeded = buffer.complete && succeeded;
304 if (!views.empty() || location >
getSize() || length > (
getSize() - location)) {
308 size_t remaining = length;
309 uint64_t current = location;
312 if (!view || view.empty()) {
317 const size_t chunk = view.size() < remaining ? view.size() : remaining;
318 if (!views.append(view.first(chunk))) {
331 uint64_t current = location;
332 for (
size_t i = 0; i < views.count(); ++i) {
335 current += view.size();
363 if (count > MaxSyncPages || (count && !locations))
365 for (
size_t i = 0; i < count; ++i) {
369 bool succeeded =
true;
370 for (
size_t i = 0; i < count; ++i)
371 succeeded =
sync(locations[i],
false) && succeeded;
391 const uint64_t base = location - location % 512;
392 const size_t within = location - base;
393 auto view =
read(base);
396 if (within >= view.size()) {
400 const size_t available = view.size() - within;
401 const size_t amount = length < available ? length : available;
402 ByteSet(
reinterpret_cast<void*
>(view.address() + within), 0, amount);
@ Disk
A disk device - a block device in UNIX terms.
static DiskReadView borrowed(const void *data, size_t size)
virtual bool sync(uint64_t location, bool async)
virtual bool getPartitionUuid(String &uuid) const
virtual void align(uint64_t location)
Sets the page boundary alignment after a specific location on the disk.
void unpinViews(uint64_t location, BufferViewSequence &views)
virtual void dump(String &str)
virtual BufferView read(uint64_t location)
virtual size_t getSize() const
Gets the size of the disk.
virtual MUST_USE_RESULT bool readIntoBatch(ReadBuffer *buffers, size_t count)
virtual void getName(String &str)
virtual MUST_USE_RESULT bool zero(uint64_t location, size_t length)
virtual void unpin(uint64_t location)=0
virtual MUST_USE_RESULT bool writeFromBatch(WriteBuffer *buffers, size_t count)
virtual MUST_USE_RESULT bool readInto(uint64_t location, void *buffer, size_t length)
virtual MUST_USE_RESULT bool syncPages(const uint64_t *locations, size_t count)
virtual PagingStatus preparePagingTransport(PagingTransport *&transport)
MUST_USE_RESULT bool readViews(uint64_t location, size_t length, BufferViewSequence &views)
virtual void write(uint64_t location)
virtual void flush(uint64_t location)
Flush a cached page to disk.
virtual size_t getNativeBlockSize() const
virtual DiskReadView readView(uint64_t location)
virtual size_t getBlockSize() const
Gets the preferred I/O extent of the disk.
virtual MUST_USE_RESULT bool retireCachePage(uint64_t location)
virtual MUST_USE_RESULT bool syncData()
virtual MUST_USE_RESULT bool syncAll()
virtual bool cacheIsCritical()
Whether or not the cache is critical and cannot be flushed or deleted.