The Pedigree Project 0.1
FatFilesystem.h
1/*
2 * Copyright (c) 2008-2014, Pedigree Developers
3 *
4 * Please see the CONTRIB file in the root of the source tree for a full
5 * list of contributors.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#ifndef FATFILESYSTEM_H
21#define FATFILESYSTEM_H
22
23#include "pedigree/kernel/LockGuard.h"
24#include "pedigree/kernel/process/Mutex.h"
25#include "pedigree/kernel/utilities/Cache.h"
26#include "pedigree/kernel/utilities/List.h"
27#include "pedigree/kernel/utilities/Tree.h"
29#include "pedigree/kernel/utilities/Vector.h"
30
31#include "FatDirectory.h"
32#include "FatFile.h"
33#include "fat.h"
34#include "modules/system/vfs/Filesystem.h"
35
37class FatFilesystem : public Filesystem {
38 friend class FatFile;
39 friend class FatDirectory;
40 friend class FatSymlink;
41
42 public:
44
45 ~FatFilesystem() override;
46
47 //
48 // Filesystem interface.
49 //
50
51 bool initialise(Disk* pDisk) override;
52 static Filesystem* probe(Disk* pDisk);
53 File* getRoot() const override;
54 const String& getVolumeLabel() const override;
55 bool getUuid(String&) const override;
56 SyncStatus sync() override;
57 SyncStatus shutdown() override;
58 uint64_t read(File* pFile, uint64_t location, uint64_t size, uintptr_t buffer,
59 bool bCanBlock = true);
60 uint64_t write(File* pFile, uint64_t location, uint64_t size, uintptr_t buffer,
61 bool bCanBlock = true);
62 void truncate(File* pFile);
63 void fileAttributeChanged(File* pFile);
64 void cacheDirectoryContents(File* pFile);
65 void extend(File* pFile, size_t size);
66
67 protected:
68 bool createFile(File* parent, const String& filename, uint32_t mask) override;
69 bool createDirectory(File* parent, const String& filename, uint32_t mask) override;
70 bool createSymlink(File* parent, const String& filename, const String& value) override;
71 bool removeNode(File* parent, const String& filename, File* file) override;
72 bool renameNode(Directory* oldParent, const String& oldName, File* source, Directory* newParent,
73 const String& newName, File* replaced) override;
74
76 void operator=(const FatFilesystem&);
77
78 void loadRootDir();
79
80 void cacheVolumeLabel();
81
83 bool readCluster(uint32_t block, uintptr_t buffer) const;
84
86 bool writeCluster(uint32_t block, uintptr_t buffer);
87
89 bool writeSectorBlock(uint32_t sec, size_t size, uintptr_t buffer);
90
92 bool readSectorBlock(uint32_t sec, size_t size, uintptr_t buffer) const;
93
95 uint32_t getSectorNumber(uint32_t cluster) const;
96
99 uint32_t getClusterEntry(uint32_t cluster, bool bLock = true);
100
103 bool setClusterEntry(uint32_t cluster, uint32_t value, bool bLock = true, bool persist = true);
104
106 String convertFilenameTo(String filename) const;
107
109 String convertFilenameFrom(String filename) const;
110
112 uint32_t findFreeCluster(bool* persisted = nullptr);
113
114 bool syncFat(bool bLock = true);
115 bool invalidateFsInfoHints();
116 bool m_FsInfoInvalidated = false;
117 uint8_t* getFatSector(uint32_t sector);
118 bool chainExtent(File* file, uint32_t& count, uint32_t& last);
119 uint32_t fileClusterAt(File*, size_t);
120 uint64_t m_ChainRevision = 1;
121 bool truncateFile(File* file);
122 class ShrinkPlan;
123 bool prepareFileShrink(FatFile*, size_t, UniquePointer<File::PreparedShrink>&);
124 bool trimFileAllocation(FatFile*);
125 void publishSize(File*, size_t);
126 void unlinkNode(File*);
127 void retireNode(File*);
128 void moveNode(File*, uint32_t, uint32_t);
129 bool isNodeUnlinked(File*) const;
130 void writeEntryAttributes(File*, Dir*, bool creating = false);
131 void encodeEntryAttributes(const File::Attributes&, Dir*, bool creating = false);
132 bool syncNodeAttributes(File*);
133 bool syncNode(File*);
135 uint64_t slot;
136 File::Attributes attributes;
137 PendingAttributes* next = nullptr;
138 };
139 PendingAttributes* m_PendingAttributes = nullptr;
140 bool writePendingAttributes(const PendingAttributes&);
141 // Pending-attribute helpers require m_FileMutationLock.
142 bool syncPendingAttributes();
143 void movePendingAttributes(uint32_t oldCluster, uint32_t oldOffset, uint32_t newCluster,
144 uint32_t newOffset);
145 void discardPendingAttributes(uint32_t cluster, uint32_t offset);
146 void clearPendingAttributes();
147 FatFile::State* acquireFileState(FatFile*, uintptr_t, size_t, uint32_t, uint32_t, Time::Timestamp,
148 Time::Timestamp, Time::Timestamp);
149 void releaseFileState(FatFile*);
150 uintptr_t fileIdentifier(uint32_t cluster, uint32_t offset);
151 uintptr_t fileIdentifierLocked(uint64_t slot);
152 bool writeCachedPages(FatFile::State&, const Cache::WritebackPage*, size_t);
153 bool drainFileStates(bool checked = false);
154 struct NodeState {
155 uintptr_t inode = 0;
156 uint32_t directoryCluster = 0, directoryOffset = 0;
157 bool unlinked = false;
158 Vector<File*> aliases;
159 };
160 Tree<uintptr_t, NodeState*> m_NodeStates;
161 Tree<File*, NodeState*> m_NodeAliases;
162 void registerNode(File*);
163 void releaseNode(File*);
164 void moveNonFileNode(File*, uint32_t, uint32_t);
165 void unlinkNonFileNode(File*);
166 Mutex m_StateLock;
168 Tree<uint64_t, uintptr_t> m_FileIdentifiers;
169 uintptr_t m_NextFileIdentifier = 0x10000000;
170 FatFile::State* m_StateList = nullptr;
171 bool m_IoFailed = false;
172 bool m_ShutdownComplete = false;
173 bool m_MountedClean = true;
174 bool ensureCapacity(File* file, size_t size);
175 bool zeroRange(File* file, size_t begin, size_t end);
176 bool updateFileMetadata(File* file, size_t size);
177 bool syncFileMetadata(File* file);
178 uint64_t allocatedBlocks(File* file);
179
182
185 void* readDirectoryPortion(uint32_t clus) const;
186
188 bool readDirectoryPortion(uint32_t clus, uintptr_t buffer) const;
189
191 bool writeDirectoryPortion(uint32_t clus, void* p);
192
194 File* createFile(File* parentDir, const String& filename, uint32_t mask, bool bDirectory = false,
195 uint32_t dirClus = 0, bool publish = true);
196
198 bool releaseClusterChain(uint32_t clus, bool lockFile = true);
199
201 Dir* getDirectoryEntry(uint32_t clus, uint32_t offset) const;
202
204 bool writeDirectoryEntry(Dir* dir, uint32_t clus, uint32_t offset);
205
207 bool isEof(uint32_t cluster) const {
208 return (cluster >= eofValue());
209 }
210
212 uint32_t eofValue() const {
213 if (m_Type == FAT12)
214 return 0x0FF8;
215 if (m_Type == FAT16)
216 return 0xFFF8;
217 if (m_Type == FAT32)
218 return 0x0FFFFFF8;
219 return 0;
220 }
221
222 Time::Timestamp getUnixTimestamp(uint16_t time, uint16_t date) const;
223 uint16_t getFatDate(Time::Timestamp timestamp) const;
224 uint16_t getFatTime(Time::Timestamp timestamp) const;
225
228 Superblock16 m_Superblock16;
229 Superblock32 m_Superblock32;
230 FSInfo32 m_FsInfo;
231
233 FatType m_Type;
234
236 uint64_t m_DataAreaStart; // data area can potentially start above 4 GB
237 uint32_t m_RootDirCount;
238
240 uint16_t m_FatSector;
241
244 uint32_t sector; // FAT12 and 16 don't use a cluster
245 uint32_t cluster; // but FAT32 does...
246 } m_RootDir;
247
249 uint32_t m_BlockSize;
250
253
255 uint8_t* m_pFatCache;
256
258 // Mutex m_FatLock;
260
261#if THREADS || defined(STANDALONE_MUTEXES)
264#endif
265
268
269 // FAT cache
270 // Cache<uint8_t*, 512> m_FatCache;
272 Tree<uint32_t, bool> m_DirtyFatSectors;
273
279
282};
283
284#endif
Definition Disk.h:35
File * getRoot() const override
bool renameNode(Directory *oldParent, const String &oldName, File *source, Directory *newParent, const String &newName, File *replaced) override
uint32_t eofValue() const
SyncStatus sync() override
bool writeSectorBlock(uint32_t sec, size_t size, uintptr_t buffer)
String convertFilenameTo(String filename) const
uint32_t findFreeCluster(bool *persisted=nullptr)
uint32_t m_ClusterCount
bool writeCluster(uint32_t block, uintptr_t buffer)
Mutex m_FileMutationLock
uint32_t m_BlockSize
uint8_t * m_pFatCache
SyncStatus shutdown() override
void * readDirectoryPortion(uint32_t clus) const
uint32_t m_FreeClusterHint
bool writeDirectoryPortion(uint32_t clus, void *p)
UnlikelyLock m_FatLock
bool createFile(File *parent, const String &filename, uint32_t mask) override
String convertFilenameFrom(String filename) const
Dir * getDirectoryEntry(uint32_t clus, uint32_t offset) const
uint16_t m_FatSector
bool createDirectory(File *parent, const String &filename, uint32_t mask) override
bool removeNode(File *parent, const String &filename, File *file) override
bool isEof(uint32_t cluster) const
uint32_t getClusterEntry(uint32_t cluster, bool bLock=true)
const String & getVolumeLabel() const override
uint32_t getSectorNumber(uint32_t cluster) const
uint64_t m_DataAreaStart
bool setClusterEntry(uint32_t cluster, uint32_t value, bool bLock=true, bool persist=true)
bool createSymlink(File *parent, const String &filename, const String &value) override
bool readSectorBlock(uint32_t sec, size_t size, uintptr_t buffer) const
Superblock m_Superblock
bool getUuid(String &) const override
bool readCluster(uint32_t block, uintptr_t buffer) const
bool initialise(Disk *pDisk) override
bool releaseClusterChain(uint32_t clus, bool lockFile=true)
bool writeDirectoryEntry(Dir *dir, uint32_t clus, uint32_t offset)
Definition File.h:74
Definition Mutex.h:56
A key/value dictionary.
Definition Tree.h:33
A vector / dynamic array.
Definition Vector.h:33
Definition ext2.h:201
Definition fat.h:91