21 #include "Filesystem.h" 22 #include "pedigree/kernel/LockGuard.h" 23 #include "pedigree/kernel/Log.h" 24 #include "pedigree/kernel/process/Scheduler.h" 25 #include "pedigree/kernel/process/Thread.h" 26 #include "pedigree/kernel/processor/PhysicalMemoryManager.h" 27 #include "pedigree/kernel/processor/Processor.h" 28 #include "pedigree/kernel/processor/ProcessorInformation.h" 29 #include "pedigree/kernel/processor/VirtualAddressSpace.h" 30 #include "pedigree/kernel/processor/types.h" 31 #include "pedigree/kernel/utilities/Iterator.h" 32 #include "pedigree/kernel/utilities/Pair.h" 33 #include "pedigree/kernel/utilities/Result.h" 34 #include "pedigree/kernel/utilities/assert.h" 35 #include "pedigree/kernel/utilities/utility.h" 38 CacheConstants::CallbackCause cause, uintptr_t loc, uintptr_t page,
41 File *pFile =
reinterpret_cast<File *
>(meta);
45 case CacheConstants::WriteBack:
56 case CacheConstants::Eviction:
62 WARNING(
"File: unknown cache callback -- could indicate potential " 63 "future I/O issues.");
69 : m_Name(), m_AccessedTime(0), m_ModifiedTime(0), m_CreationTime(0),
70 m_Inode(0), m_pFilesystem(0), m_Size(0), m_pParent(0), m_nWriters(0),
71 m_nReaders(0), m_Uid(0), m_Gid(0), m_Permissions(0),
72 m_DataCache(FILE_BAD_BLOCK), m_bDirect(false)
79 m_Lock(), m_MonitorTargets()
85 const String &name, Time::Timestamp accessedTime,
86 Time::Timestamp modifiedTime, Time::Timestamp creationTime, uintptr_t inode,
88 : m_Name(name), m_AccessedTime(accessedTime), m_ModifiedTime(modifiedTime),
89 m_CreationTime(creationTime), m_Inode(inode), m_pFilesystem(pFs),
90 m_Size(size), m_pParent(pParent), m_nWriters(0), m_nReaders(0), m_Uid(0),
91 m_Gid(0), m_Permissions(0), m_DataCache(FILE_BAD_BLOCK), m_bDirect(false)
98 m_Lock(), m_MonitorTargets()
116 File::read(uint64_t location, uint64_t size, uintptr_t buffer,
bool bCanBlock)
125 if ((location + size) >= m_Size)
127 size_t oldSize = size;
128 size = m_Size - location;
129 if ((location + size) > m_Size)
133 "VFS: even after fixup, read at location " 134 << location <<
" is larger than file size (" << m_Size <<
")");
136 "VFS: fixup size: " << size
137 <<
", original size: " << oldSize);
142 const size_t blockSize =
148 if (location >= m_Size)
151 uintptr_t block = location / blockSize;
152 uintptr_t offs = location % blockSize;
153 uintptr_t sz = (size + offs > blockSize) ? blockSize - offs : size;
156 if (sz > (m_Size - location))
157 sz = m_Size - location;
160 if (buff == FILE_BAD_BLOCK)
163 "File::read - failed to get page from cache, returning early");
170 reinterpret_cast<void *>(buffer),
171 reinterpret_cast<void *>(buff + offs), sz);
183 File::write(uint64_t location, uint64_t size, uintptr_t buffer,
bool bCanBlock)
194 bool isEntireBlock =
false;
195 if ((location % blockSize) == 0)
197 if ((size % blockSize) == 0)
199 isEntireBlock =
true;
204 extend(location + size, location, size);
209 uintptr_t block = location / blockSize;
210 uintptr_t offs = location % blockSize;
211 uintptr_t sz = (size + offs > blockSize) ? blockSize - offs : size;
214 if (buff == FILE_BAD_BLOCK)
217 "File::read - failed to get page from cache, returning early");
222 reinterpret_cast<void *>(buff + offs),
223 reinterpret_cast<void *>(buffer), sz);
234 if (location >= m_Size)
237 fileAttributeChanged();
246 WARNING(
"File in direct mode, cannot get backing page.");
256 blockSize = nativeBlockSize;
258 offset &= ~(blockSize - 1);
267 uintptr_t vaddr = FILE_BAD_BLOCK;
281 vaddr = FILE_BAD_BLOCK;
285 if ((!vaddr) || (vaddr == FILE_BAD_BLOCK))
292 if (va.
isMapped(reinterpret_cast<void *>(vaddr)))
294 physical_uintptr_t phys = 0;
296 va.
getMapping(reinterpret_cast<void *>(vaddr), phys, flags);
328 blockSize = nativeBlockSize;
330 offset &= ~(blockSize - 1);
358 for (
size_t i = 0; i < m_DataCache.count(); ++i)
360 auto result = m_DataCache.getNth(i);
361 if (result.hasError())
366 uintptr_t buffer = result.value().second();
367 if (buffer != FILE_BAD_BLOCK)
380 return m_CreationTime;
386 fileAttributeChanged();
391 return m_AccessedTime;
397 fileAttributeChanged();
402 return m_ModifiedTime;
408 fileAttributeChanged();
421 size_t File::getSize()
426 void File::setSize(
size_t sz)
456 uintptr_t File::getInode()
const 461 void File::setInode(uintptr_t inode)
468 return m_pFilesystem;
476 void File::fileAttributeChanged()
480 void File::increaseRefCount(
bool bIsWriter)
488 void File::decreaseRefCount(
bool bIsWriter)
496 void File::setPermissions(uint32_t perms)
498 m_Permissions = perms;
499 fileAttributeChanged();
502 uint32_t File::getPermissions()
const 504 return m_Permissions;
507 void File::setUid(
size_t uid)
510 fileAttributeChanged();
513 size_t File::getUid()
const 518 void File::setGid(
size_t gid)
521 fileAttributeChanged();
524 size_t File::getGid()
const 529 File *File::getParent()
const 583 uint64_t location, uint64_t size, uintptr_t buffer,
bool bCanBlock)
587 FATAL(
"A bytewise File subclass didn't implement readBytewise");
593 uint64_t location, uint64_t size, uintptr_t buffer,
bool bCanBlock)
597 FATAL(
"A bytewise File subclass didn't implement writeBytewise");
617 if (m_Size < newSize)
641 m_Permissions = perms;
662 it != m_MonitorTargets.end(); it++)
672 m_MonitorTargets.clear();
687 m_MonitorTargets.pushBack(
new MonitorTarget(pThread, pEvent));
697 it != m_MonitorTargets.end(); it++)
701 if (pMT->pThread == pThread)
704 m_MonitorTargets.erase(it);
705 it = m_MonitorTargets.begin();
706 if (it == m_MonitorTargets.end())
725 if (getParent() != 0)
729 while ((f = f->getParent()))
745 if (bWithLabel && m_pFilesystem)
752 else if (bWithLabel && !m_pFilesystem)
754 ERROR(
"File::getFullPath called without a filesystem!");
767 auto result = m_DataCache.lookup(key);
768 if (result.hasValue())
770 return result.value();
774 return FILE_BAD_BLOCK;
787 if (m_DataCache.contains(key))
789 if (value == FILE_BAD_BLOCK)
791 m_DataCache.remove(key);
795 m_DataCache.update(key, value);
800 m_DataCache.insert(key, value);
812 return blockSize < nativeBlockSize;
821 size_t offset = block * blockSize;
822 size_t mask = blockSize - 1;
825 mask = nativeBlockSize - 1;
828 size_t blockOffset = offset & mask;
837 bool didExist =
false;
842 if (didExist && !m_bDirect)
849 for (
size_t i = 0; i < nativeBlockSize; i += blockSize)
851 uintptr_t blockAddr =
readBlock(offset + i);
854 reinterpret_cast<void *>(vaddr),
855 reinterpret_cast<void *>(blockAddr), blockSize);
860 NOTICE(
"readIntoCache: fillcache blockOffset=" << blockOffset);
861 return vaddr + blockOffset;
865 uintptr_t buff = FILE_BAD_BLOCK;
870 if (buff == FILE_BAD_BLOCK)
876 "File::readIntoCache - bad read (" 877 << (block * blockSize) <<
" - block size is " << blockSize
879 return FILE_BAD_BLOCK;
888 return buff + blockOffset;
virtual bool isFifo() const
static void writeCallback(CacheConstants::CallbackCause cause, uintptr_t loc, uintptr_t page, void *meta)
virtual int command(const size_t command, void *buffer)
static size_t getPageSize() PURE
virtual void pinBlock(uint64_t location)
uintptr_t insert(uintptr_t key, bool *alreadyExisted=nullptr)
Time::Timestamp getAccessedTime()
virtual void getMapping(void *virtualAddress, physical_uintptr_t &physicalAddress, size_t &flags)=0
void setUidOnly(size_t uid)
virtual int select(bool bWriting=false, int timeout=0)
virtual physical_uintptr_t getPhysicalPage(size_t offset)
void markNoLongerEditing(uintptr_t key, size_t length=0)
void monitor(Thread *pThread, Event *pEvent)
virtual void returnPhysicalPage(size_t offset)
bool useFillCache() const
virtual bool isBytewise() const
virtual bool supports(const size_t command) const
virtual bool isMapped(void *virtualAddress)=0
virtual size_t getBlockSize() const
virtual uint64_t readBytewise(uint64_t location, uint64_t size, uintptr_t buffer, bool bCanBlock=true)
static ProcessorInformation & information()
Time::Timestamp getCreationTime()
uintptr_t readIntoCache(uintptr_t block)
void cullMonitorTargets(Thread *pThread)
void setCreationTime(Time::Timestamp t)
void setPermissionsOnly(uint32_t perms)
bool sendEvent(Event *pEvent)
void evict(uint64_t location)
uintptr_t lookup(uintptr_t key)
virtual void unpinBlock(uint64_t location)
virtual void writeBlock(uint64_t location, uintptr_t addr)
void getFilesystemLabel(HugeStaticString &s)
uintptr_t getCachedPage(size_t block, bool locked=true)
virtual String getFullPath(bool bWithLabel=true)
::Iterator< T, node_t > Iterator
void setCachedPage(size_t block, uintptr_t value, bool locked=true)
void setGidOnly(size_t gid)
static Scheduler & instance()
void setModifiedTime(Time::Timestamp t)
virtual bool isSocket() const
virtual bool isPipe() const
virtual uint64_t read(uint64_t location, uint64_t size, uintptr_t buffer, bool bCanBlock=true) final
void release(uintptr_t key)
virtual void preallocate(size_t expectedSize, bool zero=true)
Time::Timestamp getModifiedTime()
virtual uintptr_t readBlock(uint64_t location)
virtual String getVolumeLabel() const =0
virtual bool isDirectory()
virtual void extend(size_t newSize)
virtual uint64_t writeBytewise(uint64_t location, uint64_t size, uintptr_t buffer, bool bCanBlock=true)
void setAccessedTime(Time::Timestamp t)
virtual uint64_t write(uint64_t location, uint64_t size, uintptr_t buffer, bool bCanBlock=true) final