21#include "pedigree/kernel/LockGuard.h"
22#include "pedigree/kernel/syscallError.h"
24#include "FatFilesystem.h"
27 Time::Timestamp creationTime, uintptr_t inode,
class Filesystem* pFs,
size_t size,
28 uint32_t dirClus, uint32_t dirOffset,
File* pParent)
29 :
File(name, accessedTime, modifiedTime, creationTime, inode, pFs, size, pParent),
31 this, inode, size, dirClus, dirOffset, accessedTime, modifiedTime, creationTime)),
32 m_DirClus(m_State->directoryCluster),
33 m_DirOffset(m_State->directoryOffset),
34 m_MetadataDirty(m_State->metadataDirty),
35 m_TrimPending(m_State->trimPending),
36 m_RetiredClusters(m_State->retiredClusters) {
39 m_NextAlias = m_State->aliases;
40 m_State->aliases =
this;
42 copyStateAttributes();
43 File::setInode(m_State->inode);
44 File::setSize(m_State->size);
45 setPermissionsOnly(FILE_UR | FILE_UW | FILE_UX | FILE_GR | FILE_GW | FILE_GX | FILE_OR | FILE_OW |
50 :
File(
String(), state.accessed, state.modified, state.changed, state.inode, state.filesystem,
54 m_DirClus(state.directoryCluster),
55 m_DirOffset(state.directoryOffset),
56 m_MetadataDirty(state.metadataDirty),
57 m_TrimPending(state.trimPending),
58 m_RetiredClusters(state.retiredClusters) {}
62 m_State->filesystem->releaseFileState(
this);
66 return m_State->cache;
68Mutex& FatFile::dataMutationLock() {
69 return m_State->dataLock;
71Mutex& FatFile::writeSerializationLock() {
72 return m_State->writeLock;
74size_t& FatFile::physicalPageLoans() {
75 return m_State->pageLoans;
77size_t FatFile::getSize() {
81 return reinterpret_cast<uintptr_t
>(m_State);
84void FatFile::setInode(uintptr_t inode) {
86 m_State->inode = inode;
87 m_State->chainRevision = 0;
88 File::setInode(inode);
89 for (
FatFile* alias = m_State->aliases; alias; alias = alias->m_NextAlias)
90 alias->File::setInode(inode);
97 uintptr_t buffer = cacheState().fill.
lookup(location);
102 bool didExist =
false;
103 buffer = cacheState().fill.
insert(location, &didExist);
110 if (!cacheState().fill.discardEditing(location)) {
111 WARNING(
"FatFile::readBlock could not discard a failed fill at " << location);
118 return cacheState().fill.
lookup(location);
123#if defined(PEDIGREE_BUILDUTILS)
124 return m_bForceFillCache;
136 ByteSet(
reinterpret_cast<void*
>(destination), 0, pageSize);
137 const size_t size = getSize();
138 if (location >= size)
140 const size_t expected = size - location < pageSize ? size - location : pageSize;
142 return filesystem->read(
this, location, expected, destination) == expected;
150bool FatFile::checkedWriteCallback(CacheConstants::CallbackCause cause, uintptr_t location,
151 uintptr_t page,
void* meta) {
152 State* state =
static_cast<State*
>(meta);
153 if (cause == CacheConstants::Eviction) {
155 return File::fillCacheCallback(cause, location, page, &file);
157 if (cause != CacheConstants::WriteBack)
160 return state->filesystem->writeCachedPages(*state, &entry, 1);
163bool FatFile::checkedBatchCallback(
const Cache::WritebackPage* pages,
size_t count,
void* meta) {
164 State* state =
static_cast<State*
>(meta);
165 return state->filesystem->writeCachedPages(*state, pages, count);
170 if (!m_pFilesystem->tryAcquireOperation(operation)) {
174 const bool succeeded = cacheState().fill.
syncAll(checkedBatchCallback, m_State);
175 return m_State->filesystem->syncFileMetadata(
this) && succeeded;
180 if (!m_pFilesystem->tryAcquireOperation(operation)) {
185 return cacheState().fill.
sync(offset,
true);
186 const uintptr_t key = offset;
187 const bool succeeded = cacheState().fill.
syncBatch(&key, 1, checkedBatchCallback, m_State);
188 return m_State->filesystem->syncFileMetadata(
this) && succeeded;
193 if (!m_pFilesystem->tryAcquireOperation(operation)) {
196 if (count > Cache::MaxWritebackPages || (count && !offsets))
198 uintptr_t keys[Cache::MaxWritebackPages];
199 for (
size_t i = 0; i < count; ++i)
201 const bool succeeded = cacheState().fill.
syncBatch(keys, count, checkedBatchCallback, m_State);
202 return m_State->filesystem->syncFileMetadata(
this) && succeeded;
210 Attributes attributes = File::getAttributes();
211 attributes.accessed = m_State->accessed;
212 attributes.modified = m_State->modified;
213 attributes.changed = m_State->changed;
214 attributes.inode = m_State->identifier;
215 attributes.blocks = filesystem->allocatedBlocks(file);
227void FatFile::copyStateAttributes() {
229 m_AccessedTime = m_State->accessed;
230 m_ModifiedTime = m_State->modified;
231 m_CreationTime = m_State->changed;
MUST_USE_RESULT bool syncAll()
void release(uintptr_t key)
uintptr_t insert(uintptr_t key, bool *alreadyExisted=nullptr)
MUST_USE_RESULT bool syncBatch(const uintptr_t *keys, size_t count, writeback_batch_t callback, void *metadata)
void markDirty(uintptr_t key)
bool sync(uintptr_t key, bool async)
void markNoLongerEditing(uintptr_t key, size_t length=0)
uintptr_t lookup(uintptr_t key)
MUST_USE_RESULT bool pin(uintptr_t key)
uintptr_t readBlock(uint64_t location) override
FatFile(const File &file)
bool syncPages(const uint64_t *offsets, size_t count) override
uintptr_t futexIdentity() override
bool readPage(uint64_t location, uintptr_t destination) override
bool useFillCache() const override
bool pinBlock(uint64_t location) override
void writeBlock(uint64_t location, uintptr_t addr) override
void unpinBlock(uint64_t location) override
void setPermissionsOnly(uint32_t perms)
virtual size_t getBlockSize() const