The Pedigree Project  0.1
File.cc
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 #include "File.h"
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"
36 
38  CacheConstants::CallbackCause cause, uintptr_t loc, uintptr_t page,
39  void *meta)
40 {
41  File *pFile = reinterpret_cast<File *>(meta);
42 
43  switch (cause)
44  {
45  case CacheConstants::WriteBack:
46  {
47  // We are given one dirty page. Blocks can be smaller than a page.
48  size_t off = 0;
50  off += pFile->getBlockSize())
51  {
52  pFile->writeBlock(loc + off, page + off);
53  }
54  }
55  break;
56  case CacheConstants::Eviction:
57  // Remove this page from our data cache.
59  pFile->setCachedPage(loc / pFile->getBlockSize(), FILE_BAD_BLOCK);
60  break;
61  default:
62  WARNING("File: unknown cache callback -- could indicate potential "
63  "future I/O issues.");
64  break;
65  }
66 }
67 
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)
73 #ifndef VFS_NOMMU
74  ,
75  m_FillCache()
76 #endif
77 #ifdef THREADS
78  ,
79  m_Lock(), m_MonitorTargets()
80 #endif
81 {
82 }
83 
85  const String &name, Time::Timestamp accessedTime,
86  Time::Timestamp modifiedTime, Time::Timestamp creationTime, uintptr_t inode,
87  Filesystem *pFs, size_t size, File *pParent)
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)
92 #ifndef VFS_NOMMU
93  ,
94  m_FillCache()
95 #endif
96 #ifdef THREADS
97  ,
98  m_Lock(), m_MonitorTargets()
99 #endif
100 {
101  size_t maxBlock = size / getBlockSize();
102  if (size % getBlockSize())
103  {
104  ++maxBlock;
105  }
106 
107  // Prefill the block cache with bad pages to avoid continuous resizes.
108  setCachedPage(maxBlock, FILE_BAD_BLOCK);
109 }
110 
112 {
113 }
114 
115 uint64_t
116 File::read(uint64_t location, uint64_t size, uintptr_t buffer, bool bCanBlock)
117 {
118  if (isBytewise())
119  {
120  // Have to perform bytewise reads
122  return readBytewise(location, size, buffer, bCanBlock);
123  }
124 
125  if ((location + size) >= m_Size)
126  {
127  size_t oldSize = size;
128  size = m_Size - location;
129  if ((location + size) > m_Size)
130  {
131  // Completely broken read parameters.
132  ERROR(
133  "VFS: even after fixup, read at location "
134  << location << " is larger than file size (" << m_Size << ")");
135  ERROR(
136  "VFS: fixup size: " << size
137  << ", original size: " << oldSize);
138  return 0;
139  }
140  }
141 
142  const size_t blockSize =
144 
145  size_t n = 0;
146  while (size)
147  {
148  if (location >= m_Size)
149  return n;
150 
151  uintptr_t block = location / blockSize;
152  uintptr_t offs = location % blockSize;
153  uintptr_t sz = (size + offs > blockSize) ? blockSize - offs : size;
154 
155  // Handle a possible early EOF.
156  if (sz > (m_Size - location))
157  sz = m_Size - location;
158 
159  uintptr_t buff = readIntoCache(block);
160  if (buff == FILE_BAD_BLOCK)
161  {
162  ERROR(
163  "File::read - failed to get page from cache, returning early");
164  return n;
165  }
166 
167  if (buffer)
168  {
169  ForwardMemoryCopy(
170  reinterpret_cast<void *>(buffer),
171  reinterpret_cast<void *>(buff + offs), sz);
172  buffer += sz;
173  }
174 
175  location += sz;
176  size -= sz;
177  n += sz;
178  }
179  return n;
180 }
181 
182 uint64_t
183 File::write(uint64_t location, uint64_t size, uintptr_t buffer, bool bCanBlock)
184 {
185  if (isBytewise())
186  {
187  // Have to perform bytewise reads
189  return writeBytewise(location, size, buffer, bCanBlock);
190  }
191 
192  const size_t blockSize = getBlockSize();
193 
194  bool isEntireBlock = false;
195  if ((location % blockSize) == 0)
196  {
197  if ((size % blockSize) == 0)
198  {
199  isEntireBlock = true;
200  }
201  }
202 
203  // Extend the file before writing it if needed.
204  extend(location + size, location, size);
205 
206  size_t n = 0;
207  while (size)
208  {
209  uintptr_t block = location / blockSize;
210  uintptr_t offs = location % blockSize;
211  uintptr_t sz = (size + offs > blockSize) ? blockSize - offs : size;
212 
213  uintptr_t buff = readIntoCache(block);
214  if (buff == FILE_BAD_BLOCK)
215  {
216  ERROR(
217  "File::read - failed to get page from cache, returning early");
218  return n;
219  }
220 
221  ForwardMemoryCopy(
222  reinterpret_cast<void *>(buff + offs),
223  reinterpret_cast<void *>(buffer), sz);
224 
225  // Trigger an immediate write-back - write-through cache.
226  writeBlock(block * blockSize, buff);
227 
228  location += sz;
229  buffer += sz;
230  size -= sz;
231  n += sz;
232  }
233 
234  if (location >= m_Size)
235  {
236  m_Size = location;
237  fileAttributeChanged();
238  }
239  return n;
240 }
241 
242 physical_uintptr_t File::getPhysicalPage(size_t offset)
243 {
244  if (m_bDirect)
245  {
246  WARNING("File in direct mode, cannot get backing page.");
247  return ~0UL;
248  }
249 
250 #ifndef VFS_NOMMU
251  // Sanitise input.
252  size_t blockSize = getBlockSize();
253  size_t nativeBlockSize = PhysicalMemoryManager::getPageSize();
254  if (useFillCache())
255  {
256  blockSize = nativeBlockSize;
257  }
258  offset &= ~(blockSize - 1);
259 
260  // Quick and easy exit.
261  if (offset > m_Size)
262  {
263  return ~0UL;
264  }
265 
266  // Check if we have this page in the cache.
267  uintptr_t vaddr = FILE_BAD_BLOCK;
268  if (LIKELY(!useFillCache()))
269  {
270  // Not using fill cache, this is the easy and common case.
271  vaddr = getCachedPage(offset / blockSize);
272  }
273  else
274  {
275  // Using the fill cache, because the filesystem has a block size
276  // smaller than our native page size.
277  vaddr = m_FillCache.lookup(offset);
278  if (!vaddr)
279  {
280  // Wasn't there. No physical page.
281  vaddr = FILE_BAD_BLOCK;
282  }
283  }
284 
285  if ((!vaddr) || (vaddr == FILE_BAD_BLOCK))
286  {
287  return ~0UL;
288  }
289 
290  // Look up the page now that we've confirmed it is in the cache.
291  VirtualAddressSpace &va = Processor::information().getVirtualAddressSpace();
292  if (va.isMapped(reinterpret_cast<void *>(vaddr)))
293  {
294  physical_uintptr_t phys = 0;
295  size_t flags = 0;
296  va.getMapping(reinterpret_cast<void *>(vaddr), phys, flags);
297 
298  // Pin this key in the cache down, so we don't lose it.
299  if (UNLIKELY(useFillCache()))
300  {
301  m_FillCache.pin(offset);
302  }
303  else
304  {
305  pinBlock(offset);
306  }
307 
308  return phys;
309  }
310 #endif // VFS_NOMMU
311 
312  return ~0UL;
313 }
314 
315 void File::returnPhysicalPage(size_t offset)
316 {
317  if (m_bDirect)
318  {
319  return;
320  }
321 
322 #ifndef VFS_NOMMU
323  // Sanitise input.
324  size_t blockSize = getBlockSize();
325  size_t nativeBlockSize = PhysicalMemoryManager::getPageSize();
326  if (useFillCache())
327  {
328  blockSize = nativeBlockSize;
329  }
330  offset &= ~(blockSize - 1);
331 
332  // Quick and easy exit for bad input.
333  if (offset > m_Size)
334  {
335  return;
336  }
337 
338  // Release the page. Beware - this could cause a cache evict, which will
339  // make the next read/write at this offset do real (slow) I/O.
340  if (UNLIKELY(useFillCache()))
341  {
342  m_FillCache.release(offset);
343  }
344  else
345  {
346  unpinBlock(offset);
347  }
348 #endif // VFS_NOMMU
349 }
350 
352 {
353 #ifdef THREADS
354  LockGuard<Mutex> guard(m_Lock);
355 #endif
356 
357  const size_t blockSize = getBlockSize();
358  for (size_t i = 0; i < m_DataCache.count(); ++i)
359  {
360  auto result = m_DataCache.getNth(i);
361  if (result.hasError())
362  {
363  break;
364  }
365 
366  uintptr_t buffer = result.value().second();
367  if (buffer != FILE_BAD_BLOCK)
368  {
369  writeBlock(i * blockSize, buffer);
370  }
371  }
372 }
373 
374 void File::sync(size_t offset, bool async)
375 {
376 }
377 
378 Time::Timestamp File::getCreationTime()
379 {
380  return m_CreationTime;
381 }
382 
383 void File::setCreationTime(Time::Timestamp t)
384 {
385  m_CreationTime = t;
386  fileAttributeChanged();
387 }
388 
389 Time::Timestamp File::getAccessedTime()
390 {
391  return m_AccessedTime;
392 }
393 
394 void File::setAccessedTime(Time::Timestamp t)
395 {
396  m_AccessedTime = t;
397  fileAttributeChanged();
398 }
399 
400 Time::Timestamp File::getModifiedTime()
401 {
402  return m_ModifiedTime;
403 }
404 
405 void File::setModifiedTime(Time::Timestamp t)
406 {
407  m_ModifiedTime = t;
408  fileAttributeChanged();
409 }
410 
412 {
413  return m_Name;
414 }
415 
416 void File::getName(String &s) const
417 {
418  s = m_Name;
419 }
420 
421 size_t File::getSize()
422 {
423  return m_Size;
424 }
425 
426 void File::setSize(size_t sz)
427 {
428  m_Size = sz;
429 }
430 
432 {
433  return false;
434 }
435 
437 {
438  return false;
439 }
440 
441 bool File::isPipe() const
442 {
443  return false;
444 }
445 
446 bool File::isFifo() const
447 {
448  return false;
449 }
450 
451 bool File::isSocket() const
452 {
453  return false;
454 }
455 
456 uintptr_t File::getInode() const
457 {
458  return m_Inode;
459 }
460 
461 void File::setInode(uintptr_t inode)
462 {
463  m_Inode = inode;
464 }
465 
466 Filesystem *File::getFilesystem() const
467 {
468  return m_pFilesystem;
469 }
470 
471 void File::setFilesystem(Filesystem *pFs)
472 {
473  m_pFilesystem = pFs;
474 }
475 
476 void File::fileAttributeChanged()
477 {
478 }
479 
480 void File::increaseRefCount(bool bIsWriter)
481 {
482  if (bIsWriter)
483  m_nWriters++;
484  else
485  m_nReaders++;
486 }
487 
488 void File::decreaseRefCount(bool bIsWriter)
489 {
490  if (bIsWriter)
491  m_nWriters--;
492  else
493  m_nReaders--;
494 }
495 
496 void File::setPermissions(uint32_t perms)
497 {
498  m_Permissions = perms;
499  fileAttributeChanged();
500 }
501 
502 uint32_t File::getPermissions() const
503 {
504  return m_Permissions;
505 }
506 
507 void File::setUid(size_t uid)
508 {
509  m_Uid = uid;
510  fileAttributeChanged();
511 }
512 
513 size_t File::getUid() const
514 {
515  return m_Uid;
516 }
517 
518 void File::setGid(size_t gid)
519 {
520  m_Gid = gid;
521  fileAttributeChanged();
522 }
523 
524 size_t File::getGid() const
525 {
526  return m_Gid;
527 }
528 
529 File *File::getParent() const
530 {
531  return m_pParent;
532 }
533 
534 int File::select(bool bWriting, int timeout)
535 {
536  return 1;
537 }
538 
539 bool File::supports(const size_t command) const
540 {
541  return false;
542 }
543 
544 int File::command(const size_t command, void *buffer)
545 {
546  return 0;
547 }
548 
549 size_t File::getBlockSize() const
550 {
552 }
553 
555 {
556  m_bDirect = true;
557 }
558 
560 {
561  m_bDirect = false;
562 }
563 
564 void File::preallocate(size_t expectedSize, bool zero)
565 {
566 }
567 
569 {
570 }
571 
573 {
574  return this;
575 }
576 
577 bool File::isBytewise() const
578 {
579  return false;
580 }
581 
583  uint64_t location, uint64_t size, uintptr_t buffer, bool bCanBlock)
584 {
585  if (isBytewise())
586  {
587  FATAL("A bytewise File subclass didn't implement readBytewise");
588  }
589  return 0;
590 }
591 
593  uint64_t location, uint64_t size, uintptr_t buffer, bool bCanBlock)
594 {
595  if (isBytewise())
596  {
597  FATAL("A bytewise File subclass didn't implement writeBytewise");
598  }
599  return 0;
600 }
601 
602 uintptr_t File::readBlock(uint64_t location)
603 {
604  ERROR("File: base class readBlock() called for " << getFullPath());
605  // only truly breaks on debug-enabled builds - in release builds this will
606  // just cause an error in the caller
607  assert(false);
608  return 0;
609 }
610 
611 void File::writeBlock(uint64_t location, uintptr_t addr)
612 {
613 }
614 
615 void File::extend(size_t newSize)
616 {
617  if (m_Size < newSize)
618  m_Size = newSize;
619 }
620 
621 void File::extend(size_t newSize, uint64_t location, uint64_t size)
622 {
623  extend(newSize);
624 }
625 
626 void File::pinBlock(uint64_t location)
627 {
628 }
629 
630 void File::unpinBlock(uint64_t location)
631 {
632 }
633 
634 void File::evict(uint64_t location)
635 {
636  setCachedPage(location / getBlockSize(), FILE_BAD_BLOCK);
637 }
638 
639 void File::setPermissionsOnly(uint32_t perms)
640 {
641  m_Permissions = perms;
642 }
643 
644 void File::setUidOnly(size_t uid)
645 {
646  m_Uid = uid;
647 }
648 
649 void File::setGidOnly(size_t gid)
650 {
651  m_Gid = gid;
652 }
653 
655 {
656 #ifdef THREADS
657  bool bAny = false;
658  {
659  LockGuard<Mutex> guard(m_Lock);
660 
661  for (List<MonitorTarget *>::Iterator it = m_MonitorTargets.begin();
662  it != m_MonitorTargets.end(); it++)
663  {
664  MonitorTarget *pMT = *it;
665 
666  pMT->pThread->sendEvent(pMT->pEvent);
667  delete pMT;
668 
669  bAny = true;
670  }
671 
672  m_MonitorTargets.clear();
673  }
674 
675  // If anything was waiting on a change, wake it up now.
676  if (bAny)
677  {
679  }
680 #endif
681 }
682 
683 void File::monitor(Thread *pThread, Event *pEvent)
684 {
685 #ifdef THREADS
686  LockGuard<Mutex> guard(m_Lock);
687  m_MonitorTargets.pushBack(new MonitorTarget(pThread, pEvent));
688 #endif
689 }
690 
692 {
693 #ifdef THREADS
694  LockGuard<Mutex> guard(m_Lock);
695 
696  for (List<MonitorTarget *>::Iterator it = m_MonitorTargets.begin();
697  it != m_MonitorTargets.end(); it++)
698  {
699  MonitorTarget *pMT = *it;
700 
701  if (pMT->pThread == pThread)
702  {
703  delete pMT;
704  m_MonitorTargets.erase(it);
705  it = m_MonitorTargets.begin();
706  if (it == m_MonitorTargets.end())
707  return;
708  }
709  }
710 #endif
711 }
712 
714 {
715  s = m_pFilesystem->getVolumeLabel();
716 }
717 
718 String File::getFullPath(bool bWithLabel)
719 {
720  HugeStaticString str;
721  HugeStaticString tmp;
722  str.clear();
723  tmp.clear();
724 
725  if (getParent() != 0)
726  str = getName();
727 
728  File *f = this;
729  while ((f = f->getParent()))
730  {
731  // This feels a bit weird considering the while loop's subject...
732  if (f->getParent())
733  {
734  tmp = str;
735  str = f->getName();
736  str += "/";
737  str += tmp;
738  }
739  }
740 
741  tmp = str;
742  str = "/";
743  str += tmp;
744 
745  if (bWithLabel && m_pFilesystem)
746  {
747  tmp = str;
748  getFilesystemLabel(str);
749  str += "ยป";
750  str += tmp;
751  }
752  else if (bWithLabel && !m_pFilesystem)
753  {
754  ERROR("File::getFullPath called without a filesystem!");
755  }
756 
757  return String(str);
758 }
759 
760 uintptr_t File::getCachedPage(size_t block, bool locked)
761 {
762 #ifdef THREADS
763  LockGuard<Mutex> guard(m_Lock, locked);
764 #endif
765 
766  DataCacheKey key(block);
767  auto result = m_DataCache.lookup(key);
768  if (result.hasValue())
769  {
770  return result.value();
771  }
772  else
773  {
774  return FILE_BAD_BLOCK;
775  }
776 }
777 
778 void File::setCachedPage(size_t block, uintptr_t value, bool locked)
779 {
780 #ifdef THREADS
781  LockGuard<Mutex> guard(m_Lock, locked);
782 #endif
783 
784  assert(value);
785 
786  DataCacheKey key(block);
787  if (m_DataCache.contains(key))
788  {
789  if (value == FILE_BAD_BLOCK)
790  {
791  m_DataCache.remove(key);
792  }
793  else
794  {
795  m_DataCache.update(key, value);
796  }
797  }
798  else
799  {
800  m_DataCache.insert(key, value);
801  }
802 }
803 
804 bool File::useFillCache() const
805 {
806 #ifdef VFS_NOMMU
807  // No fill cache in NOMMU builds.
808  return false;
809 #else
810  size_t blockSize = getBlockSize();
811  size_t nativeBlockSize = PhysicalMemoryManager::getPageSize();
812  return blockSize < nativeBlockSize;
813 #endif
814 }
815 
816 uintptr_t File::readIntoCache(uintptr_t block)
817 {
818  size_t blockSize = getBlockSize();
819  size_t nativeBlockSize = PhysicalMemoryManager::getPageSize();
820 
821  size_t offset = block * blockSize;
822  size_t mask = blockSize - 1;
823  if (useFillCache())
824  {
825  mask = nativeBlockSize - 1;
826  }
827 
828  size_t blockOffset = offset & mask;
829  offset &= ~mask;
830 
831 #ifndef VFS_NOMMU
832  if (useFillCache())
833  {
834  // Using Cache::insert() here is atomic compared to if we did a
835  // lookup() followed by an insert() - means we don't need to lock the
836  // File object to do this.
837  bool didExist = false;
838  uintptr_t vaddr =
839  m_FillCache.insert(offset, nativeBlockSize, &didExist);
840 
841  // If in direct mode we are required to read() again
842  if (didExist && !m_bDirect)
843  {
844  // Already in cache - don't re-read the file.
845  return vaddr;
846  }
847 
848  // Read the blocks
849  for (size_t i = 0; i < nativeBlockSize; i += blockSize)
850  {
851  uintptr_t blockAddr = readBlock(offset + i);
853  ForwardMemoryCopy(
854  reinterpret_cast<void *>(vaddr),
855  reinterpret_cast<void *>(blockAddr), blockSize);
856  }
857 
858  m_FillCache.markNoLongerEditing(offset, nativeBlockSize);
859 
860  NOTICE("readIntoCache: fillcache blockOffset=" << blockOffset);
861  return vaddr + blockOffset;
862  }
863 #endif
864 
865  uintptr_t buff = FILE_BAD_BLOCK;
866  if (!m_bDirect)
867  {
868  buff = getCachedPage(block);
869  }
870  if (buff == FILE_BAD_BLOCK)
871  {
872  buff = readBlock(block * blockSize);
873  if (!buff)
874  {
875  ERROR(
876  "File::readIntoCache - bad read ("
877  << (block * blockSize) << " - block size is " << blockSize
878  << ")");
879  return FILE_BAD_BLOCK;
880  }
881 
882  if (!m_bDirect)
883  {
884  setCachedPage(block, buff);
885  }
886  }
887 
888  return buff + blockOffset;
889 }
void enableDirect()
Definition: File.cc:554
virtual bool isFifo() const
Definition: File.cc:446
static void writeCallback(CacheConstants::CallbackCause cause, uintptr_t loc, uintptr_t page, void *meta)
Definition: File.cc:37
void disableDirect()
Definition: File.cc:559
virtual int command(const size_t command, void *buffer)
Definition: File.cc:544
virtual void pinBlock(uint64_t location)
Definition: File.cc:626
Cache m_FillCache
Definition: File.h:379
uintptr_t insert(uintptr_t key, bool *alreadyExisted=nullptr)
Definition: Cache.cc:258
Time::Timestamp getAccessedTime()
Definition: File.cc:389
virtual void getMapping(void *virtualAddress, physical_uintptr_t &physicalAddress, size_t &flags)=0
void setUidOnly(size_t uid)
Definition: File.cc:644
virtual int select(bool bWriting=false, int timeout=0)
Definition: File.cc:534
virtual physical_uintptr_t getPhysicalPage(size_t offset)
Definition: File.cc:242
void markNoLongerEditing(uintptr_t key, size_t length=0)
Definition: Cache.cc:919
void monitor(Thread *pThread, Event *pEvent)
Definition: File.cc:683
virtual void returnPhysicalPage(size_t offset)
Definition: File.cc:315
bool useFillCache() const
Definition: File.cc:804
virtual bool isBytewise() const
Definition: File.cc:577
virtual bool supports(const size_t command) const
Definition: File.cc:539
virtual bool isMapped(void *virtualAddress)=0
virtual size_t getBlockSize() const
Definition: File.cc:549
virtual uint64_t readBytewise(uint64_t location, uint64_t size, uintptr_t buffer, bool bCanBlock=true)
Definition: File.cc:582
Definition: String.h:49
static ProcessorInformation & information()
Definition: Processor.cc:45
Time::Timestamp getCreationTime()
Definition: File.cc:378
uintptr_t readIntoCache(uintptr_t block)
Definition: File.cc:816
void cullMonitorTargets(Thread *pThread)
Definition: File.cc:691
virtual bool isSymlink()
Definition: File.cc:431
void setCreationTime(Time::Timestamp t)
Definition: File.cc:383
void setPermissionsOnly(uint32_t perms)
Definition: File.cc:639
#define WARNING(text)
Definition: Log.h:78
bool sendEvent(Event *pEvent)
Definition: Thread.cc:529
void evict(uint64_t location)
Definition: File.cc:634
uintptr_t lookup(uintptr_t key)
Definition: Cache.cc:235
virtual void unpinBlock(uint64_t location)
Definition: File.cc:630
virtual void writeBlock(uint64_t location, uintptr_t addr)
Definition: File.cc:611
File()
Definition: File.cc:68
void getFilesystemLabel(HugeStaticString &s)
Definition: File.cc:713
#define NOTICE(text)
Definition: Log.h:74
uintptr_t getCachedPage(size_t block, bool locked=true)
Definition: File.cc:760
virtual String getFullPath(bool bWithLabel=true)
Definition: File.cc:718
::Iterator< T, node_t > Iterator
Definition: List.h:71
void setCachedPage(size_t block, uintptr_t value, bool locked=true)
Definition: File.cc:778
#define assert(x)
Definition: assert.h:37
void dataChanged()
Definition: File.cc:654
void setGidOnly(size_t gid)
Definition: File.cc:649
static Scheduler & instance()
Definition: Scheduler.h:48
void setModifiedTime(Time::Timestamp t)
Definition: File.cc:405
virtual bool isSocket() const
Definition: File.cc:451
virtual bool isPipe() const
Definition: File.cc:441
virtual uint64_t read(uint64_t location, uint64_t size, uintptr_t buffer, bool bCanBlock=true) final
Definition: File.cc:116
void release(uintptr_t key)
Definition: Cache.cc:578
virtual void preallocate(size_t expectedSize, bool zero=true)
Definition: File.cc:564
String getName() const
Definition: File.cc:411
Time::Timestamp getModifiedTime()
Definition: File.cc:400
bool pin(uintptr_t key)
Definition: Cache.cc:557
virtual void truncate()
Definition: File.cc:568
Definition: Thread.h:54
Definition: Event.h:48
virtual uintptr_t readBlock(uint64_t location)
Definition: File.cc:602
virtual String getVolumeLabel() const =0
#define ERROR(text)
Definition: Log.h:82
virtual ~File()
Definition: File.cc:111
virtual void sync()
Definition: File.cc:351
virtual File * open()
Definition: File.cc:572
virtual bool isDirectory()
Definition: File.cc:436
void yield()
Definition: Scheduler.cc:135
#define FATAL(text)
Definition: Log.h:89
Definition: File.h:66
virtual void extend(size_t newSize)
Definition: File.cc:615
virtual uint64_t writeBytewise(uint64_t location, uint64_t size, uintptr_t buffer, bool bCanBlock=true)
Definition: File.cc:592
void setAccessedTime(Time::Timestamp t)
Definition: File.cc:394
virtual uint64_t write(uint64_t location, uint64_t size, uintptr_t buffer, bool bCanBlock=true) final
Definition: File.cc:183