2#include "pedigree/kernel/utilities/assert.h"
3#include "pedigree/kernel/utilities/utility.h"
7size_t QuotaTable::position(uint32_t
id)
const {
8 size_t first = 0, last = m_Entries.count();
10 const size_t middle = first + (last - first) / 2;
11 if (m_Entries[middle].
id <
id)
20 const size_t index = position(
id);
21 return index < m_Entries.count() && m_Entries[index].id ==
id ? &m_Entries[index] :
nullptr;
25 const size_t index = position(
id);
26 return index < m_Entries.count() && m_Entries[index].id ==
id ? &m_Entries[index] :
nullptr;
30 const size_t index = position(
id);
31 if (index < m_Entries.count() && m_Entries[index].id ==
id)
32 return &m_Entries[index];
33 if (!m_Entries.tryReserve(m_Entries.count() + 1))
37 entry.record.valid = Quota::Supported;
38 m_Entries.insert(index, entry);
39 return &m_Entries[index];
42QuotaStatus QuotaTable::set(uint32_t
id,
const QuotaRecord& requested) {
43 if (requested.valid & ~Quota::Limits)
44 return QuotaStatus::Unsupported;
45 if (((requested.valid & Quota::BlockLimits) && requested.blockSoftLimit) ||
46 ((requested.valid & Quota::InodeLimits) && requested.inodeSoftLimit))
47 return QuotaStatus::Unsupported;
48 if (((requested.valid & Quota::BlockLimits) && requested.blockHardLimit > 0xffffffffULL) ||
49 ((requested.valid & Quota::InodeLimits) && requested.inodeHardLimit > 0xffffffffULL))
50 return QuotaStatus::Overflow;
51 Entry* entry = prepare(
id);
53 return QuotaStatus::NoMemory;
54 if (requested.valid & Quota::BlockLimits)
55 entry->record.blockHardLimit = requested.blockHardLimit;
56 if (requested.valid & Quota::InodeLimits)
57 entry->record.inodeHardLimit = requested.inodeHardLimit;
59 return QuotaStatus::Success;
62QuotaStatus QuotaTable::canCharge(
const Entry& entry, uint64_t bytes, uint64_t inodes,
64 const auto& record = entry.record;
65 constexpr uint64_t MaximumSpace = 0xffffffffULL * 1024;
66 if (record.currentSpace > MaximumSpace || bytes > MaximumSpace - record.currentSpace ||
67 record.currentInodes > 0xffffffffULL || inodes > 0xffffffffULL - record.currentInodes)
68 return QuotaStatus::Overflow;
70 ((bytes && record.blockHardLimit &&
71 record.currentSpace + bytes > record.blockHardLimit * 1024) ||
72 (inodes && record.inodeHardLimit && record.currentInodes + inodes > record.inodeHardLimit)))
73 return QuotaStatus::Limit;
74 return QuotaStatus::Success;
77void QuotaTable::charge(Entry& entry, uint64_t bytes, uint64_t inodes) {
78 entry.record.currentSpace += bytes;
79 entry.record.currentInodes += inodes;
83void QuotaTable::refund(Entry& entry, uint64_t bytes, uint64_t inodes) {
84 assert(bytes <= entry.record.currentSpace && inodes <= entry.record.currentInodes);
85 entry.record.currentSpace -= bytes;
86 entry.record.currentInodes -= inodes;
91 return a.blockHardLimit == b.blockHardLimit && a.blockSoftLimit == b.blockSoftLimit &&
92 a.currentSpace == b.currentSpace && a.inodeHardLimit == b.inodeHardLimit &&
93 a.inodeSoftLimit == b.inodeSoftLimit && a.currentInodes == b.currentInodes &&
94 a.blockTime == b.blockTime && a.inodeTime == b.inodeTime && a.valid == b.valid;
97void QuotaTable::clear() {
101 m_Entries.swap(other.m_Entries);
104QuotaStatus QuotaOld::decode(
const void* bytes,
size_t length,
QuotaRecord& record) {
105 if (!bytes || length != RecordSize)
106 return QuotaStatus::Invalid;
108 MemoryCopy(words, bytes, RecordSize);
110 record.blockHardLimit = words[0];
111 record.blockSoftLimit = words[1];
112 record.currentSpace =
static_cast<uint64_t
>(words[2]) * 1024;
113 record.inodeHardLimit = words[3];
114 record.inodeSoftLimit = words[4];
115 record.currentInodes = words[5];
116 record.blockTime = words[6];
117 record.inodeTime = words[7];
118 record.valid = Quota::Supported;
119 return QuotaStatus::Success;
122QuotaStatus QuotaOld::encode(
const QuotaRecord& record,
void* bytes,
size_t length) {
123 if (!bytes || length != RecordSize)
124 return QuotaStatus::Invalid;
125 if (record.blockHardLimit > 0xffffffffULL || record.blockSoftLimit > 0xffffffffULL ||
126 record.currentSpace > 0xffffffffULL * 1024 || record.inodeHardLimit > 0xffffffffULL ||
127 record.inodeSoftLimit > 0xffffffffULL || record.currentInodes > 0xffffffffULL ||
128 record.blockTime > 0xffffffffULL || record.inodeTime > 0xffffffffULL)
129 return QuotaStatus::Overflow;
130 const uint32_t words[8] = {
static_cast<uint32_t
>(record.blockHardLimit),
131 static_cast<uint32_t
>(record.blockSoftLimit),
132 static_cast<uint32_t
>((record.currentSpace + 1023) / 1024),
133 static_cast<uint32_t
>(record.inodeHardLimit),
134 static_cast<uint32_t
>(record.inodeSoftLimit),
135 static_cast<uint32_t
>(record.currentInodes),
136 static_cast<uint32_t
>(record.blockTime),
137 static_cast<uint32_t
>(record.inodeTime)};
138 MemoryCopy(bytes, words, RecordSize);
139 return QuotaStatus::Success;
142bool QuotaOld::looksLikeNewFormat(
const void* bytes,
size_t length) {
143 if (!bytes || length <
sizeof(uint32_t))
146 MemoryCopy(&magic, bytes,
sizeof(magic));
147 magic = LITTLE_TO_HOST32(magic);
148 return magic == 0xd9c01f11U || magic == 0xd9c01927U;