The Pedigree Project 0.1
File.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 FILE_H
21#define FILE_H
22#include "pedigree/kernel/LockGuard.h"
23#include "pedigree/kernel/compiler.h"
24#include "pedigree/kernel/process/Event.h"
25#include "pedigree/kernel/process/Mutex.h"
26#include "pedigree/kernel/process/OperationBarrier.h"
27#include "pedigree/kernel/process/Readiness.h"
28#include "pedigree/kernel/processor/types.h"
29#include "pedigree/kernel/time/Time.h"
30#include "pedigree/kernel/utilities/Cache.h"
31#include "pedigree/kernel/utilities/CacheConstants.h"
32#include "pedigree/kernel/utilities/HashTable.h"
33#include "pedigree/kernel/utilities/List.h"
34#include "pedigree/kernel/utilities/Pointers.h"
35#include "pedigree/kernel/utilities/StaticString.h"
36#include "pedigree/kernel/utilities/String.h"
37#include "pedigree/kernel/utilities/new"
38
39#include <config.h>
40
41#include "ExtendedAttributes.h"
42#include "FileEvent.h"
43#include "FileHandle.h"
44
45class Filesystem;
46class Thread;
47
48// RWX for owner.
49#define FILE_UR 0001
50#define FILE_UW 0002
51#define FILE_UX 0004
52#define FILE_UMASK 0007
53#define FILE_UBITS 0
54// RWX for group.
55#define FILE_GR 0010
56#define FILE_GW 0020
57#define FILE_GX 0040
58#define FILE_GMASK 0070
59#define FILE_GBITS 3
60// RWX for others.
61#define FILE_OR 0100
62#define FILE_OW 0200
63#define FILE_OX 0400
64#define FILE_OMASK 0700
65#define FILE_OBITS 6
66// Ancillary file bits.
67#define FILE_STICKY 01000
68#define FILE_AMASK 07000
69#define FILE_ABITS 9
70
71#define FILE_BAD_BLOCK static_cast<uintptr_t>(-1)
72
75class EXPORTED_PUBLIC File : public ReadinessSource, public FileEventSource {
76 friend class Filesystem;
77 friend class Directory;
78#if defined(PEDIGREE_BUILDUTILS)
79 friend class Ext2FillCacheTestPeer;
80 friend class Ext2WritebackTestPeer;
81#endif
82
83 public:
85 public:
88 File* get() const {
89 return m_Parent;
90 }
91 void swap(ParentLease& other);
92
93 private:
94 friend class File;
95 NOT_COPYABLE_OR_ASSIGNABLE(ParentLease);
96 File* m_Parent;
97 bool m_Retained;
98#if THREADS && !defined(STANDALONE_MUTEXES)
99 TerminationDeferral m_TerminationDeferral;
100#endif
101 };
102
105 public:
106 ~WriteGuard();
107
108 uint64_t write(uint64_t location, uint64_t size, uintptr_t buffer, bool bCanBlock = true,
109 bool publishMetadata = true);
110 uint64_t append(uint64_t size, uintptr_t buffer, uint64_t& location, bool bCanBlock = true,
111 bool publishMetadata = true);
112
113 private:
114 friend class File;
115
116 explicit WriteGuard(File& file);
117
118 File& m_File;
119 LockGuard<Mutex> m_Guard;
120 bool m_MetadataPending = false;
121 };
122
124 File();
125
127 private:
128 File(const File& file);
129 File& operator=(const File&);
130
131 public:
133 File(const String& name, Time::Timestamp accessedTime, Time::Timestamp modifiedTime,
134 Time::Timestamp creationTime, uintptr_t inode, class Filesystem* pFs, size_t size,
135 File* pParent);
137 virtual ~File();
138
144 virtual uint64_t read(uint64_t location, uint64_t size, uintptr_t buffer,
145 bool bCanBlock = true) final;
149 size_t readCached(uint64_t location, size_t size, uintptr_t buffer,
150 bool (*prepare)(uintptr_t, size_t) = nullptr);
154 virtual uint64_t write(uint64_t location, uint64_t size, uintptr_t buffer,
155 bool bCanBlock = true) final;
156
158 uint64_t append(uint64_t size, uintptr_t buffer, uint64_t& location, bool bCanBlock = true);
159
161 WriteGuard lockWrites();
162
166 virtual physical_uintptr_t getPhysicalPage(size_t offset);
167 virtual bool isDirectPhysicalMapping() const {
168 return false;
169 }
170 size_t physicalMappingFlags() const {
171 return m_PhysicalMappingFlags;
172 }
173
179 virtual void returnPhysicalPage(size_t offset);
181 virtual bool tryBeginMappingRelease();
182 void endMappingRelease();
183
187 bool syncAndReturnPhysicalPage(size_t offset, bool async);
188
195 virtual bool sync();
196
198 bool syncRange(size_t offset, size_t length);
199
204 virtual bool sync(size_t offset, bool async);
205
207 virtual bool syncPages(const uint64_t* offsets, size_t count);
208
210 Time::Timestamp getCreationTime();
212 void setCreationTime(Time::Timestamp t);
213
215 Time::Timestamp getAccessedTime();
217 void setAccessedTime(Time::Timestamp t);
218
220 Time::Timestamp getModifiedTime();
222 void setModifiedTime(Time::Timestamp t);
223
224 void setTimes(Time::Timestamp accessed, Time::Timestamp modified, bool changeAccessed,
225 bool changeModified);
226
227 struct Attributes {
228 Time::Timestamp accessed = 0;
229 Time::Timestamp modified = 0;
230 Time::Timestamp changed = 0;
231 size_t uid = 0;
232 size_t gid = 0;
233 uint32_t permissions = 0;
234 size_t size = 0;
235 size_t links = 1;
236 uint64_t blocks = 0;
237 // Filesystems with mutable storage identifiers may supply a stable public inode.
238 uint64_t inode = 0;
239 };
240
241 enum AttributeMask : uint32_t {
242 AccessTime = 1U << 0,
243 ModifyTime = 1U << 1,
244 ChangeTime = 1U << 2,
245 Owner = 1U << 3,
246 Group = 1U << 4,
247 Permissions = 1U << 5
248 };
249
250 virtual Attributes getAttributes() const;
251
254 virtual XattrStatus getExtendedAttribute(const StringView& name, void* buffer, size_t capacity,
255 size_t& required);
256 virtual XattrStatus listExtendedAttributes(void* buffer, size_t capacity, size_t& required);
257 virtual XattrStatus setExtendedAttribute(const StringView& name, const void* value, size_t length,
258 unsigned flags);
259 virtual XattrStatus removeExtendedAttribute(const StringView& name);
260
262 virtual bool prepareSharedMapping(size_t offset, size_t length);
263
265 String getName() const;
266 void getName(String& s) const;
267
269 virtual void getFullPath(String& result, bool bWithMount = true);
270
272 virtual String getFullPath(bool bWithMount = true);
273
275 virtual void truncate();
276
278 bool resize(size_t size);
279
281 size_t oldSize;
282 size_t newSize;
283 const Cache::DiscardReference* mappingLoans;
284 size_t mappingLoanCount;
285 };
286
288 public:
289 virtual ~PreparedShrink() = default;
291 virtual void commit() = 0;
292 };
293
294 virtual size_t getSize();
295 void setSize(size_t sz);
296
298 virtual bool isSymlink();
299
301 virtual bool isDirectory();
302 virtual bool isBlockDevice() const {
303 return false;
304 }
305 virtual uint64_t deviceNumber() const {
306 return 0;
307 }
308
310 virtual bool isPipe() const;
311
313 virtual bool isFifo() const;
314
316 virtual bool isSocket() const;
317
319 virtual bool isSeekable() const;
320
322 bool supportsRegularFileOperations();
323 virtual bool isCharacterDevice() const {
324 return false;
325 }
326 virtual bool isConsole() const {
327 return false;
328 }
329
331 virtual uint64_t maximumFileSize() const;
332
334 virtual bool allowMapping(bool shared, bool writeRequested, bool& mayWrite);
335
337 bool acquireMappingUse(bool executable, bool sharedWrite);
338 void releaseMappingUse(bool executable, bool sharedWrite);
339
340 uintptr_t getInode() const;
341 virtual void setInode(uintptr_t inode);
342
344 virtual uintptr_t futexIdentity();
345
346 Filesystem* getFilesystem() const;
347 void setFilesystem(Filesystem* pFs);
348
349 virtual void fileAttributeChanged();
350
352 void publishEvent(FileEventMask mask, const StringView& name = StringView(),
353 bool targetIsDirectory = false);
354
355 virtual FileHandleStatus subscribeInodeEvents(FileEventMask mask,
356 const SharedPointer<FileEventObserver>& observer,
357 FileEventSubscription& subscription);
358 virtual void finishInodeRetirement();
359
360 virtual void increaseRefCount(bool bIsWriter);
361 virtual void decreaseRefCount(bool bIsWriter);
362
369 virtual bool retainVfsReference();
370
372 virtual void releaseVfsReference();
373
375 virtual bool isStableVfsRoot() const;
376
377 void setPermissions(uint32_t perms);
378 uint32_t getPermissions() const;
379
380 bool setOwnership(size_t uid, size_t gid, bool changeUid, bool changeGid);
381 void setUid(size_t uid);
382 size_t getUid() const;
383
384 void setGid(size_t gid);
385 size_t getGid() const;
386
387 File* getParent() const;
388
390 void getNamespace(ParentLease& parent, String& name) const;
391
397 virtual int select(bool bWriting = false, int timeout = 0);
398
400 virtual ReadyMask queryReady(bool reading, bool writing);
401
403 virtual bool supportsReadinessNotifications() const;
404
409 void monitor(Thread* pThread, Event* pEvent);
410
412 void cullMonitorTargets(Thread* pThread);
413
415 void cullMonitorTargets(Event* pEvent);
416
418 virtual bool supports(const size_t command) const;
419
421 virtual int command(const size_t command, void* buffer);
422
425 virtual size_t getBlockSize() const;
426
428 void markPageExternallyWritable(size_t offset);
429
430 static constexpr size_t MaxReadPages = 32;
434 size_t populateRange(size_t offset, size_t length);
435
437 void enableDirect();
438
440 void disableDirect();
441
443 virtual void preallocate(size_t expectedSize, bool zero = true);
444
446 bool allocateRange(size_t offset, size_t length, bool keepSize = false);
447
454 virtual File* open();
455
458 virtual File* openForDescriptor(RetainedFile& owner);
459
460 protected:
461 bool tryAcquireFilesystemOperation(OperationBarrier::Lease& operation) const;
462 virtual void updateAttributes(const Attributes& attributes, uint32_t mask);
463 virtual bool changeOwnership(size_t uid, size_t gid, bool changeUid, bool changeGid);
464 virtual bool allowPhysicalPage() const {
465 return true;
466 }
467 virtual bool prepareWrite(uint64_t location, uint64_t size);
468 virtual bool allowResize(size_t oldSize, size_t newSize);
469 virtual bool prepareShrink(const ShrinkContext& context, UniquePointer<PreparedShrink>& prepared);
470 virtual bool resizeFile(size_t size);
472 virtual bool allocateFileRange(size_t offset, size_t length);
473 virtual Mutex& writeSerializationLock();
474 virtual Mutex& dataMutationLock();
475 virtual size_t& physicalPageLoans();
477 bool clearDataCache();
483 virtual bool isBytewise() const;
484
486 virtual uint64_t readBytewise(uint64_t location, uint64_t size, uintptr_t buffer,
487 bool bCanBlock = true);
489 virtual uint64_t writeBytewise(uint64_t location, uint64_t size, uintptr_t buffer,
490 bool bCanBlock = true);
491
500 virtual uintptr_t readBlock(uint64_t location);
502 virtual bool readPage(uint64_t location, uintptr_t destination);
503 struct ReadPage {
504 uint64_t offset;
505 uintptr_t buffer;
506 bool complete;
507 };
510 virtual bool readPages(ReadPage* pages, size_t count);
511
516 virtual void writeBlock(uint64_t location, uintptr_t addr);
517
519 virtual void writeBlocks(uint64_t location, uintptr_t addr, size_t length);
520
522 virtual void extend(size_t newSize);
523
530 virtual void extend(size_t newSize, uint64_t location, uint64_t size);
531
532 virtual void publishInodeEvent(const FileEvent& event);
533
535 void dataChanged();
536
538 void getFilesystemLabel(HugeStaticString& s);
539
547 static bool writeCallback(CacheConstants::CallbackCause cause, uintptr_t loc, uintptr_t page,
548 void* meta);
549
550 static bool fillCacheCallback(CacheConstants::CallbackCause cause, uintptr_t loc, uintptr_t page,
551 void* meta);
552
554 void enableFillCacheWriteback();
555 void shutdownFillCacheWriteback();
556
558 bool syncFillCache(size_t offset, bool async, bool& present);
559
561 virtual bool useFillCache() const;
562
576 MUST_USE_RESULT virtual bool pinBlock(uint64_t location);
577
584 MUST_USE_RESULT virtual uintptr_t acquireCachedBlock(uint64_t location, bool retryChanged);
585
589 virtual void unpinBlock(uint64_t location);
590
599 void evict(uint64_t location);
600
602 void setPermissionsOnly(uint32_t perms);
603
605 void setUidOnly(size_t uid);
606
608 void setGidOnly(size_t gid);
609
611 void retainDetachedParent();
612
613 void moveNamespace(const String& name, File* parent);
614
615 bool snapshotNamespace(ParentLease& parent, String& name, FileEventMask interest) const;
616
617 String m_Name;
618 Time::Timestamp m_AccessedTime;
619 Time::Timestamp m_ModifiedTime;
620 Time::Timestamp m_CreationTime;
621 uintptr_t m_Inode;
622 uintptr_t m_FutexIdentity = 0;
623
624 class Filesystem* m_pFilesystem;
625 size_t m_Size;
626
627 File* m_pParent;
628 mutable Mutex m_MetadataLock;
629
632 bool m_bDetachedParentHandled;
633
634 size_t m_nWriters, m_nReaders;
635
636 size_t m_Uid;
637 size_t m_Gid;
638 uint32_t m_Permissions;
639
640 public:
642 public:
643 DataCacheKey() = default;
644 DataCacheKey(size_t block) : m_Block(block) {}
645 ~DataCacheKey() = default;
646
647 size_t hash() const {
648 return m_Block;
649 }
650
651 bool operator==(const DataCacheKey& other) const {
652 return m_Block == other.m_Block;
653 }
654
655 private:
656 size_t m_Block = ~static_cast<size_t>(0);
657 };
658
659 struct CacheState {
660 CacheState();
662 Mutex indexLock;
663 Cache fill;
664 Mutex fillLock;
665 // Aliases share these counts and serialize admission with data mutation.
666 size_t executableMappings = 0;
667 size_t sharedWriteMappings = 0;
668 };
669
670 protected:
671 virtual CacheState& cacheState();
672 CacheState m_CacheState;
673
674 bool m_bDirect;
675#if defined(PEDIGREE_BUILDUTILS)
676 bool m_bForceFillCache = false;
677#endif
678
681 Mutex m_DataMutationLock;
682 size_t m_PhysicalPageLoans = 0;
683 size_t m_PhysicalMappingFlags = 0;
684
685 void setPhysicalMappingFlags(size_t flags) {
686 m_PhysicalMappingFlags = flags;
687 }
688
689 Mutex m_Lock;
690
692 MonitorTarget(Thread* pT, Event* pE, Event::SendLease registration)
693 : pThread(pT), pEvent(pE), eventRegistration(pedigree_std::move(registration)) {}
694 Thread* pThread;
695 Event* pEvent;
696 Event::SendLease eventRegistration;
697 };
698
699 List<MonitorTarget*> m_MonitorTargets;
700
701 private:
702 void publishWriteMetadata();
703
705 uint64_t writeUnlocked(uint64_t location, uint64_t size, uintptr_t buffer, bool bCanBlock);
706
708 uintptr_t getCachedPage(size_t block, bool locked = true);
709
711 void setCachedPage(size_t block, uintptr_t value, bool locked = true);
712
718 uintptr_t readIntoCache(uintptr_t block, bool overwriteWholePage = false,
719 size_t readAheadBytes = 0);
720 size_t populateRangeLocked(size_t offset, size_t length);
721
723 void releaseReadReference(uintptr_t block);
724};
725
726#endif
Definition Cache.h:207
Definition Event.h:49
virtual void commit()=0
Definition File.h:75
File * m_pDetachedParent
Definition File.h:631
File(const File &file)
Mutex m_WriteLock
Definition File.h:680
Definition Group.h:32
Definition List.h:61
Definition Mutex.h:56
bool operator==(const Iterator< originalT, Struct, FunctionPrev, FunctionNext, T1 > &x1, const Iterator< originalT, Struct, FunctionPrev, FunctionNext, T2 > &x2)
Definition Iterator.h:256