2#include "pedigree/kernel/LockGuard.h"
3#include "pedigree/kernel/syscallError.h"
6#include "Ext2Filesystem.h"
9QuotaStatus Ext2File::beginQuota(
QuotaTable& loaded) {
15 if (m_State->quotaFile || __atomic_load_n(&m_State->pageLoans, __ATOMIC_ACQUIRE))
16 return QuotaStatus::Busy;
17 if (!m_State->allocationValid || !LITTLE_TO_HOST16(m_pInode->i_links_count))
18 return QuotaStatus::Invalid;
19 if (!m_nSize || m_nSize % QuotaOld::RecordSize)
20 return QuotaStatus::Invalid;
21 auto status = m_pExt2Fs->prepareQuotaInodeLocked(m_InodeNumber);
22 if (status != QuotaStatus::Success)
24 status = m_pExt2Fs->m_Quota.exempt(m_InodeNumber,
true);
25 if (status != QuotaStatus::Success)
27 __atomic_store_n(&m_State->quotaFile,
true, __ATOMIC_RELEASE);
28 m_OwnsQuotaProtection =
true;
33 uint8_t bytes[QuotaOld::RecordSize];
34 for (uint64_t offset = 0; offset < getSize(); offset +=
sizeof(bytes)) {
36 if (
read(offset,
sizeof(bytes),
reinterpret_cast<uintptr_t
>(bytes)) !=
sizeof(bytes))
37 return m_pExt2Fs->quotaIoStatus();
38 if (!offset && QuotaOld::looksLikeNewFormat(bytes,
sizeof(bytes)))
39 return QuotaStatus::Invalid;
41 auto status = QuotaOld::decode(bytes,
sizeof(bytes), record);
42 if (status != QuotaStatus::Success)
44 if (record.blockSoftLimit || record.inodeSoftLimit ||
45 (offset && (record.blockTime || record.inodeTime)))
46 return QuotaStatus::Unsupported;
47 if (offset && !record.blockHardLimit && !record.inodeHardLimit)
49 auto* entry = loaded.prepare(
static_cast<uint32_t
>(offset /
sizeof(bytes)));
51 return QuotaStatus::NoMemory;
52 entry->record = record;
54 return QuotaStatus::Success;
57QuotaStatus Ext2File::endQuota(QuotaType type,
bool requireClean) {
62 if (!m_OwnsQuotaProtection)
63 return QuotaStatus::Success;
65 for (
const auto& entry : m_pExt2Fs->m_Quota.table(type).entries()) {
67 return QuotaStatus::Busy;
70 const auto status = m_pExt2Fs->m_Quota.exempt(m_InodeNumber,
false);
71 if (status != QuotaStatus::Success)
73 m_pExt2Fs->m_Quota.disable(type);
74 __atomic_store_n(&m_State->quotaFile,
false, __ATOMIC_RELEASE);
75 m_OwnsQuotaProtection =
false;
76 return QuotaStatus::Success;
79QuotaStatus Ext2File::writeQuotaRecord(uint32_t
id,
const QuotaRecord& record) {
80 uint8_t bytes[QuotaOld::RecordSize];
81 const auto status = QuotaOld::encode(record, bytes,
sizeof(bytes));
82 if (status != QuotaStatus::Success)
84 const uint64_t offset =
static_cast<uint64_t
>(id) *
sizeof(bytes);
86 return QuotaStatus::TooLarge;
91 m_State->quotaInternalWrite =
true;
93 const uint64_t written = writes.write(offset,
sizeof(bytes),
reinterpret_cast<uintptr_t
>(bytes));
94 m_State->quotaInternalWrite =
false;
95 return written ==
sizeof(bytes) ? QuotaStatus::Success : m_pExt2Fs->quotaIoStatus();
virtual uint64_t maximumFileSize() const override
virtual uint64_t read(uint64_t location, uint64_t size, uintptr_t buffer, bool bCanBlock=true) final