Advertisement
Guest User

Untitled

a guest
Jun 4th, 2017
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 124.31 KB | None | 0 0
  1. Index: src/add-ons/kernel/file_systems/ext2/InodeJournal.h
  2. ===================================================================
  3. --- src/add-ons/kernel/file_systems/ext2/InodeJournal.h (revision 0)
  4. +++ src/add-ons/kernel/file_systems/ext2/InodeJournal.h (revision 0)
  5. @@ -0,0 +1,29 @@
  6. +/*
  7. + * Copyright 2001-2010, Haiku Inc. All rights reserved.
  8. + * This file may be used under the terms of the MIT License.
  9. + *
  10. + * Authors:
  11. + *     Janito V. Ferreira Filho
  12. + */
  13. +#ifndef INODEJOURNAL_H
  14. +#define INODEJOURNAL_H
  15. +
  16. +
  17. +#include "Inode.h"
  18. +#include "Journal.h"
  19. +
  20. +
  21. +class InodeJournal : public Journal {
  22. +public:
  23. +                       InodeJournal(Inode* inode);
  24. +                       ~InodeJournal();
  25. +
  26. +           status_t    InitCheck();
  27. +          
  28. +           status_t    MapBlock(uint32 logical, uint32& physical);
  29. +private:
  30. +           Inode*      fInode;
  31. +           status_t    fInitStatus;
  32. +};
  33. +
  34. +#endif // INODEJOURNAL_H
  35. Index: src/add-ons/kernel/file_systems/ext2/InodeAllocator.cpp
  36. ===================================================================
  37. --- src/add-ons/kernel/file_systems/ext2/InodeAllocator.cpp (revision 0)
  38. +++ src/add-ons/kernel/file_systems/ext2/InodeAllocator.cpp (revision 0)
  39. @@ -0,0 +1,110 @@
  40. +/*
  41. + * Copyright 2001-2010, Haiku Inc. All rights reserved.
  42. + * This file may be used under the terms of the MIT License.
  43. + *
  44. + * Authors:
  45. + *     Janito V. Ferreira Filho
  46. + */
  47. +
  48. +#include "InodeAllocator.h"
  49. +
  50. +#include <util/AutoLock.h>
  51. +
  52. +#include "BitmapBlock.h"
  53. +#include "Volume.h"
  54. +
  55. +
  56. +//#define TRACE_EXT2
  57. +#ifdef TRACE_EXT2
  58. +#  define TRACE(x...) dprintf("\33[34mext2:\33[0m " x)
  59. +#else
  60. +#  define TRACE(x...) ;
  61. +#endif
  62. +
  63. +
  64. +InodeAllocator::InodeAllocator(Volume* volume)
  65. +   :
  66. +   fVolume(volume)
  67. +{
  68. +   mutex_init(&fLock, "ext2 inode allocator");
  69. +}
  70. +
  71. +
  72. +InodeAllocator::~InodeAllocator()
  73. +{
  74. +   mutex_destroy(&fLock);
  75. +}
  76. +
  77. +
  78. +status_t
  79. +InodeAllocator::New(Transaction& transaction, uint32 preferredBlockGroup,
  80. +   ino_t& id)
  81. +{
  82. +   MutexLocker lock(fLock);
  83. +
  84. +   uint32 blockGroup = preferredBlockGroup;
  85. +   uint32 lastBlockGroup = fVolume->NumGroups() - 1;
  86. +
  87. +   for (int i = 0; i < 2; ++i) {
  88. +       for (; blockGroup < lastBlockGroup; ++blockGroup) {
  89. +           ext2_block_group* group;
  90. +
  91. +           status_t status = fVolume->GetBlockGroup(blockGroup, &group);
  92. +           if (status != B_OK)
  93. +               return status;
  94. +
  95. +           if (group->FreeInodes() != 0) {
  96. +               return _MarkInBitmap(transaction, group->InodeBitmap(),
  97. +                   blockGroup, fVolume->InodesPerGroup(), id);
  98. +           }
  99. +       }
  100. +
  101. +       if (i == 0) {
  102. +           ext2_block_group* group;
  103. +
  104. +           status_t status = fVolume->GetBlockGroup(blockGroup, &group);
  105. +           if (status != B_OK)
  106. +               return status;
  107. +
  108. +           if (group->FreeInodes() != 0) {
  109. +               return _MarkInBitmap(transaction, group->InodeBitmap(),
  110. +                   blockGroup, fVolume->NumInodes()
  111. +                       - blockGroup * fVolume->InodesPerGroup(), id);
  112. +           }
  113. +       }
  114. +
  115. +       blockGroup = 0;
  116. +       lastBlockGroup = preferredBlockGroup;
  117. +   }
  118. +
  119. +   return B_DEVICE_FULL;
  120. +}
  121. +
  122. +
  123. +status_t
  124. +InodeAllocator::_MarkInBitmap(Transaction& transaction, uint32 bitmapBlock,
  125. +   uint32 blockGroup, uint32 numInodes, ino_t& id)
  126. +{
  127. +   BitmapBlock inodeBitmap(fVolume, numInodes);
  128. +
  129. +   if (!inodeBitmap.SetToWritable(transaction, bitmapBlock)) {
  130. +       TRACE("Unable to open inode bitmap (block number: %lu) for block group "
  131. +           "%lu\n", bitmapBlock, blockGroup);
  132. +       return B_IO_ERROR;
  133. +   }
  134. +
  135. +   uint32 pos = 0;
  136. +   inodeBitmap.FindNextUnmarked(pos);
  137. +
  138. +   if (pos == inodeBitmap.NumBits()) {
  139. +       TRACE("Even though the block group %lu indicates there are free "
  140. +           "inodes, no unmarked bit was found in the inode bitmap at block "
  141. +           "%lu.", blockGroup, bitmapBlock);
  142. +       return B_ERROR;
  143. +   }
  144. +
  145. +   inodeBitmap.Mark(pos, true);
  146. +   id = pos + blockGroup * fVolume->InodesPerGroup();
  147. +
  148. +   return B_OK;
  149. +}
  150.  
  151. Property changes on: src/add-ons/kernel/file_systems/ext2/InodeAllocator.cpp
  152. ___________________________________________________________________
  153. Added: svn:executable
  154.    + *
  155.  
  156. Index: src/add-ons/kernel/file_systems/ext2/BlockAllocator.h
  157. ===================================================================
  158. --- src/add-ons/kernel/file_systems/ext2/BlockAllocator.h   (revision 0)
  159. +++ src/add-ons/kernel/file_systems/ext2/BlockAllocator.h   (revision 0)
  160. @@ -0,0 +1,53 @@
  161. +/*
  162. + * Copyright 2001-2010, Haiku Inc. All rights reserved.
  163. + * This file may be used under the terms of the MIT License.
  164. + *
  165. + * Authors:
  166. + *     Janito V. Ferreira Filho
  167. + */
  168. +#ifndef BLOCKALLOCATOR_H
  169. +#define BLOCKALLOCATOR_H
  170. +
  171. +#include <lock.h>
  172. +
  173. +#include "Transaction.h"
  174. +
  175. +
  176. +class AllocationBlockGroup;
  177. +class Inode;
  178. +class Volume;
  179. +
  180. +
  181. +class BlockAllocator {
  182. +public:
  183. +                       BlockAllocator(Volume* volume);
  184. +                       ~BlockAllocator();
  185. +
  186. +           status_t    Initialize();
  187. +
  188. +           status_t    AllocateBlocks(Transaction& transaction,
  189. +                           uint32 minimum, uint32 maximum, uint32& blockGroup,
  190. +                           uint32& start, uint32& length);
  191. +           status_t    Allocate(Transaction& transaction, Inode* inode,
  192. +                           off_t numBlocks, uint32 minimum, uint32& start,
  193. +                           uint32& length);
  194. +           status_t    Free(Transaction& transaction, uint32 start,
  195. +                           uint32 length);
  196. +
  197. +           uint32      FreeBlocks();
  198. +
  199. +protected:
  200. +   static  status_t    _Initialize(BlockAllocator* allocator);
  201. +
  202. +
  203. +           Volume*     fVolume;
  204. +           mutex       fLock;
  205. +
  206. +           AllocationBlockGroup* fGroups;
  207. +           uint32      fBlocksPerGroup;
  208. +           uint32      fNumBlocks;
  209. +           uint32      fNumGroups;
  210. +           uint32      fFirstBlock;
  211. +};
  212. +
  213. +#endif // BLOCKALLOCATOR_H
  214.  
  215. Property changes on: src/add-ons/kernel/file_systems/ext2/BlockAllocator.h
  216. ___________________________________________________________________
  217. Added: svn:executable
  218.    + *
  219.  
  220. Index: src/add-ons/kernel/file_systems/ext2/HTreeEntryIterator.cpp
  221. ===================================================================
  222. --- src/add-ons/kernel/file_systems/ext2/HTreeEntryIterator.cpp (revision 37473)
  223. +++ src/add-ons/kernel/file_systems/ext2/HTreeEntryIterator.cpp (working copy)
  224. @@ -11,6 +11,7 @@
  225.  
  226.  #include <new>
  227.  
  228. +#include "CachedBlock.h"
  229.  #include "HTree.h"
  230.  #include "IndexedDirectoryIterator.h"
  231.  #include "Inode.h"
  232. @@ -27,81 +28,91 @@
  233.  
  234.  HTreeEntryIterator::HTreeEntryIterator(off_t offset, Inode* directory)
  235.     :
  236. +   fDirectory(directory),
  237. +   fVolume(directory->GetVolume()),
  238.     fHasCollision(false),
  239. -   fDirectory(directory),
  240. -   fOffset(offset),
  241. +   fBlockSize(directory->GetVolume()->BlockSize()),
  242.     fParent(NULL),
  243.     fChild(NULL)
  244.  {
  245. -   fBlockSize = fDirectory->GetVolume()->BlockSize();
  246. +   fInitStatus = fDirectory->FindBlock(offset, fBlockNum);
  247. +
  248. +   if (fInitStatus == B_OK)
  249. +       fDisplacement = offset % fBlockSize;
  250. +
  251. +   TRACE("HTreeEntryIterator::HTreeEntryIterator() block %lu displacement "
  252. +       "%lu\n", fBlockNum, fDisplacement);
  253.  }
  254.  
  255.  
  256.  HTreeEntryIterator::HTreeEntryIterator(uint32 block, uint32 blockSize,
  257.     Inode* directory, HTreeEntryIterator* parent, bool hasCollision)
  258.     :
  259. +   fDirectory(directory),
  260. +   fVolume(directory->GetVolume()),
  261.     fHasCollision(hasCollision),
  262.     fBlockSize(blockSize),
  263. -   fDirectory(directory),
  264. -   fOffset(block * blockSize + sizeof(HTreeFakeDirEntry)),
  265. +   fBlockNum(block),
  266. +   fDisplacement(0),
  267.     fParent(parent),
  268.     fChild(NULL)
  269.  {
  270. -   TRACE("HTreeEntryIterator::HTreeEntryIterator() block %ld offset %Lx\n",
  271. -       block, fOffset);
  272. +   fInitStatus = B_OK;
  273. +
  274. +   TRACE("HTreeEntryIterator::HTreeEntryIterator() block %lu displacement %lu\n",
  275. +       block, fDisplacement);
  276.  }
  277.  
  278.  
  279.  status_t
  280.  HTreeEntryIterator::Init()
  281.  {
  282. -   size_t length = sizeof(HTreeCountLimit);
  283. -   HTreeCountLimit countLimit;
  284. -  
  285. -   status_t status = fDirectory->ReadAt(fOffset, (uint8*)&countLimit,
  286. -       &length);
  287. -  
  288. -   if (status != B_OK)
  289. -       return status;
  290. -  
  291. -   if (length != sizeof(HTreeCountLimit)) {
  292. -       ERROR("HTreeEntryIterator::Init() bad length %ld fOffset 0x%Lx\n",
  293. -           length, fOffset);
  294. +   if (fInitStatus != B_OK)
  295. +       return fInitStatus;
  296. +
  297. +   fCurrentEntry = 0;
  298. +
  299. +   CachedBlock cached(fVolume);
  300. +   const uint8* block = cached.SetTo(fBlockNum);
  301. +   if (block == NULL) {
  302. +       ERROR("Failed to read htree entry block.\n");
  303.         fCount = fLimit = 0;
  304. -       return B_ERROR;
  305. +       return B_IO_ERROR;
  306.     }
  307. -  
  308. -   fCount = countLimit.Count();
  309. -   fLimit = countLimit.Limit();
  310.  
  311. +   HTreeCountLimit* countLimit = (HTreeCountLimit*)(fBlockNum + fDisplacement);
  312. +
  313. +   fCount = countLimit->Count();
  314. +   fLimit = countLimit->Limit();
  315. +
  316.     if (fCount >= fLimit) {
  317. -       ERROR("HTreeEntryIterator::Init() bad fCount %d fOffset 0x%Lx\n",
  318. -           fCount, fOffset);
  319. +       ERROR("HTreeEntryIterator::Init() bad fCount %lu fDisplacement %lu\n",
  320. +           (uint32)fCount, fDisplacement);
  321.         fCount = fLimit = 0;
  322.         return B_ERROR;
  323.     }
  324.  
  325. -   if (fParent != NULL &&
  326. -       fLimit != ((fBlockSize - sizeof(HTreeFakeDirEntry))
  327. +   if (fLimit != ((fBlockSize - sizeof(HTreeFakeDirEntry))
  328.             / sizeof(HTreeEntry)) ) {
  329. -       ERROR("HTreeEntryIterator::Init() bad fLimit %d should be %ld "
  330. -           "fOffset 0x%Lx\n", fLimit, (fBlockSize - sizeof(HTreeFakeDirEntry))
  331. -               / sizeof(HTreeEntry), fOffset);
  332. +       ERROR("HTreeEntryIterator::Init() bad fLimit %lu should be %lu "
  333. +           "at block %lu displacement %lu\n", (uint32)fLimit,
  334. +           (fBlockSize - fDisplacement - sizeof(HTreeFakeDirEntry))
  335. +               / sizeof(HTreeEntry),
  336. +           fBlockNum, fDisplacement);
  337.         fCount = fLimit = 0;
  338.         return B_ERROR;
  339. -   }
  340. +   }
  341.  
  342.     TRACE("HTreeEntryIterator::Init() count 0x%x limit 0x%x\n", fCount,
  343.         fLimit);
  344.  
  345. -   fMaxOffset = fOffset + (fCount - 1) * sizeof(HTreeEntry);
  346. -  
  347.     return B_OK;
  348.  }
  349.  
  350.  
  351.  HTreeEntryIterator::~HTreeEntryIterator()
  352.  {
  353. +   delete fChild;
  354.  }
  355.  
  356.  
  357. @@ -109,68 +120,65 @@
  358.  HTreeEntryIterator::Lookup(uint32 hash, int indirections,
  359.     DirectoryIterator** directoryIterator)
  360.  {
  361. -   off_t start = fOffset + sizeof(HTreeEntry);
  362. -   off_t end = fMaxOffset;
  363. -   off_t middle = start;
  364. -   size_t entrySize = sizeof(HTreeEntry);
  365. -   HTreeEntry entry;
  366. -  
  367. +   CachedBlock cached(fVolume);
  368. +   const uint8* block = cached.SetTo(fBlockNum);
  369. +   if (block == NULL) {
  370. +       ERROR("Failed to read htree entry block.\n");
  371. +       // Fallback to linear search
  372. +       *directoryIterator = new(std::nothrow)
  373. +           DirectoryIterator(fDirectory);
  374. +
  375. +       if (*directoryIterator == NULL)
  376. +           return B_NO_MEMORY;
  377. +
  378. +       return B_OK;
  379. +   }
  380. +
  381. +   HTreeEntry* start = (HTreeEntry*)(block + fDisplacement) + 1;
  382. +   HTreeEntry* end = (HTreeEntry*)(block + fBlockSize - fDisplacement);
  383. +   HTreeEntry* middle = start;
  384. +
  385.     while (start <= end) {
  386. -       middle = (end - start) / 2;
  387. -       middle -= middle % entrySize; // Alignment
  388. -       middle += start;
  389. +       middle = (HTreeEntry*)(((uint8*)end - (uint8*)start) / 2
  390. +           + (uint8*)start);
  391.  
  392. -       TRACE("HTreeEntryIterator::Lookup() %d 0x%Lx 0x%Lx 0x%Lx\n",
  393. +       TRACE("HTreeEntryIterator::Lookup() indirections: %d s:%p m:%p e:%p\n",
  394.             indirections, start, end, middle);
  395. -      
  396. -       status_t status = fDirectory->ReadAt(middle, (uint8*)&entry,
  397. -           &entrySize);
  398.  
  399. -       TRACE("HTreeEntryIterator::Lookup() %lx %lx\n", hash, entry.Hash());
  400. -      
  401. -       if (status != B_OK)
  402. -           return status;
  403. -       else if (entrySize != sizeof(entry)) {
  404. -           // Fallback to linear search
  405. -           *directoryIterator = new(std::nothrow)
  406. -               DirectoryIterator(fDirectory);
  407. -          
  408. -           if (*directoryIterator == NULL)
  409. -               return B_NO_MEMORY;
  410. -          
  411. -           return B_OK;
  412. -       }
  413. -      
  414. -       if (hash >= entry.Hash())
  415. -           start = middle + entrySize;
  416. +       TRACE("HTreeEntryIterator::Lookup() %lx %lx\n", hash, middle->Hash());
  417. +
  418. +       if (hash >= middle->Hash())
  419. +           start = middle++;
  420.         else
  421. -           end = middle - entrySize;
  422. +           end = middle--;
  423.     }
  424.  
  425. -   status_t status = fDirectory->ReadAt(start - entrySize, (uint8*)&entry,
  426. -       &entrySize);
  427. -   if (status != B_OK)
  428. -       return status;
  429. -  
  430. +   --start;
  431. +
  432. +   fCurrentEntry = ((uint8*)start - block + fDisplacement)
  433. +       / sizeof(HTreeEntry);
  434. +
  435.     if (indirections == 0) {
  436.         *directoryIterator = new(std::nothrow)
  437. -           IndexedDirectoryIterator(entry.Block() * fBlockSize, fBlockSize,
  438. -           fDirectory, this);
  439. -      
  440. +           IndexedDirectoryIterator(start->Block() * fBlockSize, fDirectory,
  441. +               this);
  442. +
  443.         if (*directoryIterator == NULL)
  444.             return B_NO_MEMORY;
  445.  
  446.         return B_OK;
  447.     }
  448.  
  449. +   uint32 blockNum;
  450. +   status_t status = fDirectory->FindBlock(start->Block() * fBlockSize,
  451. +       blockNum);
  452. +
  453.     delete fChild;
  454.  
  455. -   fChild = new(std::nothrow) HTreeEntryIterator(entry.Block(), fBlockSize,
  456. -       fDirectory, this, entry.Hash() & 1 == 1);
  457. -  
  458. +   fChild = new(std::nothrow) HTreeEntryIterator(blockNum, fBlockSize,
  459. +       fDirectory, this, start->Hash() & 1 == 1);
  460.     if (fChild == NULL)
  461.         return B_NO_MEMORY;
  462. -   fChildDeleter.SetTo(fChild);
  463.    
  464.     status = fChild->Init();
  465.     if (status != B_OK)
  466. @@ -181,40 +189,37 @@
  467.  
  468.  
  469.  status_t
  470. -HTreeEntryIterator::GetNext(off_t& childOffset)
  471. +HTreeEntryIterator::GetNext(uint32& childBlock)
  472.  {
  473. -   size_t entrySize = sizeof(HTreeEntry);
  474. -   fOffset += entrySize;
  475. -   bool firstEntry = fOffset >= fMaxOffset;
  476. -  
  477. +   fCurrentEntry++;
  478. +   bool firstEntry = fCurrentEntry >= fCount;
  479. +
  480.     if (firstEntry) {
  481.         if (fParent == NULL)
  482.             return B_ENTRY_NOT_FOUND;
  483. -      
  484. -       status_t status = fParent->GetNext(fOffset);
  485. +
  486. +       status_t status = fParent->GetNext(fBlockNum);
  487.         if (status != B_OK)
  488.             return status;
  489. -      
  490. +
  491. +       fDisplacement = 0;
  492.         status = Init();
  493.         if (status != B_OK)
  494.             return status;
  495.  
  496.         fHasCollision = fParent->HasCollision();
  497.     }
  498. -  
  499. -   HTreeEntry entry;
  500. -   status_t status = fDirectory->ReadAt(fOffset, (uint8*)&entry, &entrySize);
  501. -   if (status != B_OK)
  502. -       return status;
  503. -   else if (entrySize != sizeof(entry)) {
  504. -       // Weird error, try to skip it
  505. -       return GetNext(childOffset);
  506. -   }
  507. -  
  508. +
  509. +   CachedBlock cached(fVolume);
  510. +   const uint8* block = cached.SetTo(fBlockNum);
  511. +   if (block == NULL)
  512. +       return B_IO_ERROR;
  513. +
  514. +   HTreeEntry* entry = (HTreeEntry*)(block + fDisplacement);
  515. +
  516.     if (!firstEntry)
  517. -       fHasCollision = (entry.Hash() & 1) == 1;
  518. -  
  519. -   childOffset = entry.Block() * fBlockSize;
  520. -  
  521. -   return B_OK;
  522. +       fHasCollision = (entry[fCurrentEntry].Hash() & 1) == 1;
  523. +
  524. +   return fDirectory->FindBlock(entry[fCurrentEntry].Block() * fBlockSize,
  525. +       childBlock);
  526.  }
  527. Index: src/add-ons/kernel/file_systems/ext2/Inode.h
  528. ===================================================================
  529. --- src/add-ons/kernel/file_systems/ext2/Inode.h    (revision 37473)
  530. +++ src/add-ons/kernel/file_systems/ext2/Inode.h    (working copy)
  531. @@ -23,6 +23,8 @@
  532.  
  533.             rw_lock*    Lock() { return &fLock; }
  534.  
  535. +           status_t    WriteBack(Transaction& transaction);
  536. +
  537.             bool        IsDirectory() const
  538.                             { return S_ISDIR(Mode()); }
  539.             bool        IsFile() const
  540. @@ -54,8 +56,17 @@
  541.  
  542.             ext2_inode& Node() { return *fNode; }
  543.  
  544. +   static  status_t    Create(Transaction& transaction, Inode* parent,
  545. +                           const char* name, int32 mode, int openMode,
  546. +                           uint32 type, bool* _created = NULL,
  547. +                           ino_t* _id = NULL, Inode** _inode = NULL,
  548. +                           fs_vnode_ops* vnodeOps = NULL,
  549. +                           uint32 publishFlags = 0);
  550. +
  551.             void*       FileCache() const { return fCache; }
  552.             void*       Map() const { return fMap; }
  553. +           status_t    DisableFileCache();
  554. +           bool        IsFileCacheDisabled() const { return !fCached; }
  555.  
  556.  private:
  557.                         Inode(const Inode&);
  558. @@ -63,13 +74,15 @@
  559.                             // no implementation
  560.  
  561.  private:
  562. -   rw_lock             fLock;
  563. -   ::Volume*           fVolume;
  564. -   ino_t               fID;
  565. -   void*               fCache;
  566. -   void*               fMap;
  567. -   ext2_inode*         fNode;
  568. -   ext2_xattr_header*  fAttributesBlock;
  569. +           rw_lock     fLock;
  570. +           ::Volume*   fVolume;
  571. +           ino_t       fID;
  572. +           void*       fCache;
  573. +           void*       fMap;
  574. +           bool        fCached;
  575. +           ext2_inode* fNode;
  576. +           ext2_xattr_header* fAttributesBlock;
  577. +           status_t    fInitStatus;
  578.  };
  579.  
  580.  #endif // INODE_H
  581. Index: src/add-ons/kernel/file_systems/ext2/Volume.cpp
  582. ===================================================================
  583. --- src/add-ons/kernel/file_systems/ext2/Volume.cpp (revision 37473)
  584. +++ src/add-ons/kernel/file_systems/ext2/Volume.cpp (working copy)
  585. @@ -20,7 +20,10 @@
  586.  
  587.  #include <util/AutoLock.h>
  588.  
  589. +#include "CachedBlock.h"
  590.  #include "Inode.h"
  591. +#include "InodeJournal.h"
  592. +#include "NoJournal.h"
  593.  
  594.  
  595.  //#define TRACE_EXT2
  596. @@ -199,7 +202,7 @@
  597.     // TODO: check some more values!
  598.     if (Magic() != (uint32)EXT2_SUPER_BLOCK_MAGIC)
  599.         return false;
  600. -
  601. +  
  602.     return true;
  603.  }
  604.  
  605. @@ -210,6 +213,8 @@
  606.  Volume::Volume(fs_volume* volume)
  607.     :
  608.     fFSVolume(volume),
  609. +   fBlockAllocator(this),
  610. +   fInodeAllocator(this),
  611.     fFlags(0),
  612.     fGroupBlocks(NULL),
  613.     fRootNode(NULL)
  614. @@ -229,6 +234,9 @@
  615.  
  616.         free(fGroupBlocks);
  617.     }
  618. +
  619. +   delete fJournal;
  620. +   delete fJournalInode;
  621.  }
  622.  
  623.  
  624. @@ -252,7 +260,7 @@
  625.  status_t
  626.  Volume::Mount(const char* deviceName, uint32 flags)
  627.  {
  628. -   flags |= B_MOUNT_READ_ONLY;
  629. +   // flags |= B_MOUNT_READ_ONLY;
  630.         // we only support read-only for now
  631.  
  632.     DeviceOpener opener(deviceName, (flags & B_MOUNT_READ_ONLY) != 0
  633. @@ -278,10 +286,17 @@
  634.     fBlockSize = 1UL << fSuperBlock.BlockShift();
  635.     fFirstDataBlock = fSuperBlock.FirstDataBlock();
  636.  
  637. +   fFreeBlocks = fSuperBlock.FreeBlocks();
  638. +   fFreeInodes = fSuperBlock.FreeInodes();
  639. +
  640. +   uint32 numBlocks = fSuperBlock.NumBlocks();
  641. +   uint32 blocksPerGroup = fSuperBlock.BlocksPerGroup();
  642. +   fNumGroups = numBlocks / blocksPerGroup;
  643. +   if (numBlocks % blocksPerGroup != 0)
  644. +       fNumGroups++;
  645. +
  646. +   fGroupsPerBlock = fBlockSize / sizeof(ext2_block_group);
  647.     fNumInodes = fSuperBlock.NumInodes();
  648. -   fNumGroups = (fSuperBlock.NumBlocks() - fFirstDataBlock - 1)
  649. -       / fSuperBlock.BlocksPerGroup() + 1;
  650. -   fGroupsPerBlock = fBlockSize / sizeof(ext2_block_group);
  651.  
  652.     TRACE("block size %ld, num groups %ld, groups per block %ld, first %lu\n",
  653.         fBlockSize, fNumGroups, fGroupsPerBlock, fFirstDataBlock);
  654. @@ -310,6 +325,45 @@
  655.     if (fBlockCache == NULL)
  656.         return B_ERROR;
  657.  
  658. +   // initialize journal
  659. +   if ((fSuperBlock.CompatibleFeatures() & EXT2_FEATURE_HAS_JOURNAL) != 0) {
  660. +       // TODO: There should be a mount option to ignore the existent journal
  661. +       if (fSuperBlock.JournalInode() != 0) {
  662. +           fJournalInode = new(std::nothrow) Inode(this,
  663. +               fSuperBlock.JournalInode());
  664. +
  665. +           if (fJournalInode == NULL)
  666. +               return B_NO_MEMORY;
  667. +
  668. +           TRACE("Opening an on disk, inode mapped journal.\n");
  669. +           fJournal = new(std::nothrow) InodeJournal(fJournalInode);
  670. +       } else {
  671. +           // TODO: external journal
  672. +           TRACE("Can not open an external journal.\n");
  673. +           return B_NOT_SUPPORTED;
  674. +       }
  675. +   } else {
  676. +       TRACE("Opening a fake journal (NoJournal).\n");
  677. +       fJournal = new(std::nothrow) NoJournal(this);
  678. +   }
  679. +
  680. +   if (fJournal == NULL)
  681. +       return B_NO_MEMORY;
  682. +
  683. +   status = fJournal->InitCheck();
  684. +   if (status != B_OK)
  685. +       return status;
  686. +
  687. +   // TODO: Only recover if asked to
  688. +   status = fJournal->Recover();
  689. +   if (status != B_OK)
  690. +       return status;
  691. +
  692. +   status = fJournal->StartLog();
  693. +   if (status != B_OK)
  694. +       return status;
  695. +
  696. +   // ready
  697.     status = get_vnode(fFSVolume, EXT2_ROOT_NODE, (void**)&fRootNode);
  698.     if (status != B_OK) {
  699.         TRACE("could not create root node: get_vnode() failed!\n");
  700. @@ -443,6 +497,96 @@
  701.  }
  702.  
  703.  
  704. +status_t
  705. +Volume::AllocateInode(Transaction& transaction, uint32 preferredBlockGroup,
  706. +   ino_t& id)
  707. +{
  708. +   if ((fFlags & VOLUME_READ_ONLY) != 0)
  709. +       return B_READ_ONLY_DEVICE;
  710. +
  711. +   status_t status = fInodeAllocator.New(transaction, preferredBlockGroup, id);
  712. +   if (status == B_OK)
  713. +       fFreeInodes -= 1;
  714. +
  715. +   return status;
  716. +}
  717. +
  718. +
  719. +status_t
  720. +Volume::AllocateBlocks(Transaction& transaction, uint32 blockGroup,
  721. +   uint32 minimum, uint32 maximum, uint32& start, uint32& length)
  722. +{
  723. +   if ((fFlags & VOLUME_READ_ONLY) != 0)
  724. +       return B_READ_ONLY_DEVICE;
  725. +
  726. +   status_t status = fBlockAllocator.AllocateBlocks(transaction, blockGroup,
  727. +       minimum, maximum, start, length);
  728. +   if (status != B_OK)
  729. +       return status;
  730. +
  731. +   fFreeBlocks -= length;
  732. +
  733. +   return WriteSuperBlock(transaction);
  734. +}
  735. +
  736. +
  737. +status_t
  738. +Volume::LoadSuperBlock()
  739. +{
  740. +   CachedBlock cached(this);
  741. +   const uint8* block = cached.SetTo(fFirstDataBlock);
  742. +
  743. +   if (block == NULL)
  744. +       return B_IO_ERROR;
  745. +
  746. +   if (fFirstDataBlock == 0)
  747. +       memcpy(&fSuperBlock, block + 1024, sizeof(fSuperBlock));
  748. +   else
  749. +       memcpy(&fSuperBlock, block, sizeof(fSuperBlock));
  750. +
  751. +   fFreeBlocks = fSuperBlock.FreeBlocks();
  752. +   fFreeInodes = fSuperBlock.FreeInodes();
  753. +
  754. +   return B_OK;
  755. +}
  756. +
  757. +
  758. +status_t
  759. +Volume::WriteSuperBlock(Transaction& transaction)
  760. +{
  761. +   fSuperBlock.SetFreeBlocks(fFreeBlocks);
  762. +   fSuperBlock.SetFreeInodes(fFreeInodes);
  763. +   // TODO: Rest of fields that can be modified
  764. +
  765. +   CachedBlock cached(this);
  766. +   uint8* block = cached.SetToWritable(transaction, fFirstDataBlock);
  767. +
  768. +   if (block == NULL)
  769. +       return B_IO_ERROR;
  770. +
  771. +   if (fFirstDataBlock == 0)
  772. +       memcpy(block + 1024, &fSuperBlock, sizeof(fSuperBlock));
  773. +   else
  774. +       memcpy(block, &fSuperBlock, sizeof(fSuperBlock));
  775. +
  776. +   return B_OK;
  777. +}
  778. +
  779. +
  780. +status_t
  781. +Volume::FlushDevice()
  782. +{
  783. +   return block_cache_sync(fBlockCache);
  784. +}
  785. +
  786. +
  787. +status_t
  788. +Volume::Sync()
  789. +{
  790. +   return fJournal->FlushLogAndBlocks();
  791. +}
  792. +
  793. +
  794.  // #pragma mark - Disk scanning and initialization
  795.  
  796.  
  797. @@ -460,3 +604,18 @@
  798.         ? B_OK : B_NOT_SUPPORTED;
  799.  }
  800.  
  801. +
  802. +void
  803. +Volume::TransactionDone(bool success)
  804. +{
  805. +   status_t status = LoadSuperBlock();
  806. +   if (status != B_OK)
  807. +       panic("Failed to relead ext2 superblock.\n");
  808. +}
  809. +
  810. +
  811. +void
  812. +Volume::RemovedFromTransaction()
  813. +{
  814. +   // TODO: Does it make a difference?
  815. +}
  816. Index: src/add-ons/kernel/file_systems/ext2/Journal.cpp
  817. ===================================================================
  818. --- src/add-ons/kernel/file_systems/ext2/Journal.cpp    (revision 0)
  819. +++ src/add-ons/kernel/file_systems/ext2/Journal.cpp    (revision 0)
  820. @@ -0,0 +1,990 @@
  821. +/*
  822. + * Copyright 2001-2010, Haiku Inc. All rights reserved.
  823. + * This file may be used under the terms of the MIT License.
  824. + *
  825. + * Authors:
  826. + *     Janito V. Ferreira Filho
  827. + */
  828. +
  829. +#include "Journal.h"
  830. +
  831. +#include <new>
  832. +#include <string.h>
  833. +#include <unistd.h>
  834. +
  835. +#include <fs_cache.h>
  836. +
  837. +#include "CachedBlock.h"
  838. +#include "HashRevokeManager.h"
  839. +
  840. +
  841. +//#define TRACE_EXT2
  842. +#ifdef TRACE_EXT2
  843. +#  define TRACE(x...) dprintf("\33[34mext2:\33[0m " x)
  844. +#else
  845. +#  define TRACE(x...) ;
  846. +#endif
  847. +
  848. +
  849. +class LogEntry : public DoublyLinkedListLinkImpl<LogEntry> {
  850. +public:
  851. +                           LogEntry(Journal* journal, uint32 logStart,
  852. +                               uint32 length);
  853. +                           ~LogEntry();
  854. +
  855. +           uint32          Start() const { return fStart; }
  856. +           uint32          CommitID() const { return fCommitID; }
  857. +
  858. +           Journal*        GetJournal() { return fJournal; }
  859. +
  860. +private:
  861. +           Journal*        fJournal;
  862. +           uint32          fStart;
  863. +           uint32          fCommitID;
  864. +};
  865. +
  866. +
  867. +LogEntry::LogEntry(Journal* journal, uint32 logStart, uint32 commitID)
  868. +   :
  869. +   fJournal(journal),
  870. +   fStart(logStart),
  871. +   fCommitID(commitID)
  872. +{
  873. +}
  874. +
  875. +
  876. +LogEntry::~LogEntry()
  877. +{
  878. +}
  879. +
  880. +
  881. +/*void
  882. +add_to_iovec(iovec* vecs, int32& index, int32 max, const void* address,
  883. +   size_t size)
  884. +{
  885. +   if (index > 0 && (addr_t)vecs[index - 1].iov_base
  886. +       + vecs[index - 1].iov_len == (addr_t)address) {
  887. +       // the iovec can be combined with the previous one
  888. +       vecs[index - 1].iov_len += size;
  889. +       return;
  890. +   }
  891. +
  892. +   if (index == max)
  893. +       panic("no more space for iovecs!");
  894. +  
  895. +   // start a new iovec
  896. +   vecs[index].iov_base = const_cast<void*>(address);
  897. +   vecs[index].iov_len = size;
  898. +   index++;
  899. +}*/
  900. +
  901. +
  902. +void
  903. +JournalHeader::MakeDescriptor(uint32 sequence)
  904. +{
  905. +   this->magic = B_HOST_TO_BENDIAN_INT32(JOURNAL_MAGIC);
  906. +   this->sequence = B_HOST_TO_BENDIAN_INT32(sequence);
  907. +   this->block_type = B_HOST_TO_BENDIAN_INT32(JOURNAL_DESCRIPTOR_BLOCK);
  908. +}
  909. +
  910. +
  911. +void
  912. +JournalHeader::MakeCommit(uint32 sequence)
  913. +{
  914. +   this->magic = B_HOST_TO_BENDIAN_INT32(JOURNAL_MAGIC);
  915. +   this->sequence = B_HOST_TO_BENDIAN_INT32(sequence);
  916. +   this->block_type = B_HOST_TO_BENDIAN_INT32(JOURNAL_COMMIT_BLOCK);
  917. +}
  918. +
  919. +
  920. +Journal::Journal(Volume* fsVolume, Volume* jVolume)
  921. +   :
  922. +   fJournalVolume(jVolume),
  923. +   fJournalBlockCache(jVolume->BlockCache()),
  924. +   fFilesystemVolume(fsVolume),
  925. +   fFilesystemBlockCache(fsVolume->BlockCache()),
  926. +   fRevokeManager(NULL),
  927. +   fInitStatus(B_OK),
  928. +   fBlockSize(sizeof(JournalSuperBlock)),
  929. +   fFirstCommitID(0),
  930. +   fFirstCacheCommitID(0),
  931. +   fFirstLogBlock(0),
  932. +   fLogSize(0),
  933. +   fVersion(0),
  934. +   fLogStart(0),
  935. +   fLogEnd(0),
  936. +   fFreeBlocks(0),
  937. +   fMaxTransactionSize(0),
  938. +   fCurrentCommitID(0),
  939. +   fHasSubTransaction(false),
  940. +   fSeparateSubTransactions(false)//,
  941. +   //fNextCommitID(0)
  942. +{
  943. +   recursive_lock_init(&fLock, "ext2 journal");
  944. +   mutex_init(&fLogEntriesLock, "ext2 journal log entries");
  945. +
  946. +   fRevokeManager = new(std::nothrow) HashRevokeManager;
  947. +
  948. +   if (fRevokeManager == NULL)
  949. +       fInitStatus = B_NO_MEMORY;
  950. +   else
  951. +       fInitStatus = _LoadSuperBlock();
  952. +}
  953. +
  954. +
  955. +Journal::Journal()
  956. +   :
  957. +   fJournalVolume(NULL),
  958. +   fJournalBlockCache(NULL),
  959. +   fFilesystemVolume(NULL),
  960. +   fFilesystemBlockCache(NULL),
  961. +   fRevokeManager(NULL),
  962. +   fInitStatus(B_OK),
  963. +   fBlockSize(sizeof(JournalSuperBlock)),
  964. +   fFirstCommitID(0),
  965. +   fFirstCacheCommitID(0),
  966. +   fFirstLogBlock(0),
  967. +   fLogSize(0),
  968. +   fVersion(0),
  969. +   fLogStart(0),
  970. +   fLogEnd(0),
  971. +   fFreeBlocks(0),
  972. +   fMaxTransactionSize(0),
  973. +   fCurrentCommitID(0),
  974. +   fHasSubTransaction(false),
  975. +   fSeparateSubTransactions(false)//,
  976. +   //fNextCommitID(0)
  977. +{
  978. +   recursive_lock_init(&fLock, "ext2 journal");
  979. +   mutex_init(&fLogEntriesLock, "ext2 journal log entries");
  980. +}
  981. +
  982. +
  983. +Journal::~Journal()
  984. +{
  985. +   FlushLogAndBlocks();
  986. +
  987. +   delete fRevokeManager;
  988. +
  989. +   recursive_lock_destroy(&fLock);
  990. +   mutex_destroy(&fLogEntriesLock);
  991. +}
  992. +
  993. +
  994. +status_t
  995. +Journal::InitCheck()
  996. +{
  997. +   return fInitStatus;
  998. +}
  999. +
  1000. +
  1001. +/*virtual*/ status_t
  1002. +Journal::StartLog()
  1003. +{
  1004. +   fLogStart = fFirstLogBlock;
  1005. +   fLogEnd = fFirstLogBlock;
  1006. +   fFreeBlocks = 0;
  1007. +
  1008. +   fCurrentCommitID = fFirstCommitID;
  1009. +   //fNextCommitID = fFirstCommitID;
  1010. +
  1011. +   return _SaveSuperBlock();
  1012. +}
  1013. +
  1014. +
  1015. +status_t
  1016. +Journal::RestartLog()
  1017. +{
  1018. +   fFirstCommitID = 1;
  1019. +
  1020. +   return B_OK;
  1021. +}
  1022. +
  1023. +
  1024. +status_t
  1025. +Journal::Lock(Transaction* owner, bool separateSubTransactions)
  1026. +{
  1027. +   status_t status = recursive_lock_lock(&fLock);
  1028. +   if (status != B_OK)
  1029. +       return status;
  1030. +
  1031. +   if (!fSeparateSubTransactions && recursive_lock_get_recursion(&fLock) > 1) {
  1032. +       // reuse current transaction
  1033. +       return B_OK;
  1034. +   }
  1035. +
  1036. +   if(separateSubTransactions)
  1037. +       fSeparateSubTransactions = true;
  1038. +
  1039. +   if (owner != NULL)
  1040. +       owner->SetParent(fOwner);
  1041. +
  1042. +   fOwner = owner;
  1043. +
  1044. +   if (fOwner != NULL) {
  1045. +       if (fUnwrittenTransactions > 0) {
  1046. +           // start a sub transaction
  1047. +           cache_start_sub_transaction(fFilesystemBlockCache, fTransactionID);
  1048. +           fHasSubTransaction = true;
  1049. +       } else
  1050. +           fTransactionID = cache_start_transaction(fFilesystemBlockCache);
  1051. +
  1052. +       if (fTransactionID < B_OK) {
  1053. +           recursive_lock_unlock(&fLock);
  1054. +           return fTransactionID;
  1055. +       }
  1056. +
  1057. +       cache_add_transaction_listener(fFilesystemBlockCache, fTransactionID,
  1058. +           TRANSACTION_IDLE, _TransactionIdle, this);
  1059. +   }
  1060. +
  1061. +   return B_OK;
  1062. +}
  1063. +
  1064. +
  1065. +status_t
  1066. +Journal::Unlock(Transaction* owner, bool success)
  1067. +{
  1068. +   if (fSeparateSubTransactions
  1069. +       || recursive_lock_get_recursion(&fLock) == 1) {
  1070. +       // we only end the transaction if we unlock it
  1071. +       if (owner != NULL) {
  1072. +           status_t status = _TransactionDone(success);
  1073. +           if (status != B_OK)
  1074. +               return status;
  1075. +
  1076. +           bool separateSubTransactions = fSeparateSubTransactions;
  1077. +           fSeparateSubTransactions = true;
  1078. +           owner->NotifyListeners(success);
  1079. +           fSeparateSubTransactions = separateSubTransactions;
  1080. +
  1081. +           fOwner = owner->Parent();
  1082. +       } else
  1083. +           fOwner = NULL;
  1084. +
  1085. +       if (fSeparateSubTransactions
  1086. +           && recursive_lock_get_recursion(&fLock) == 1)
  1087. +           fSeparateSubTransactions = false;
  1088. +   } else
  1089. +       owner->MoveListenersTo(fOwner);
  1090. +
  1091. +   recursive_lock_unlock(&fLock);
  1092. +   return B_OK;
  1093. +}
  1094. +
  1095. +
  1096. +status_t
  1097. +Journal::MapBlock(uint32 logical, uint32& physical)
  1098. +{
  1099. +   physical = logical;
  1100. +  
  1101. +   return B_OK;
  1102. +}
  1103. +
  1104. +
  1105. +inline uint32
  1106. +Journal::FreeLogBlocks() const
  1107. +{
  1108. +   return fLogStart <= fLogEnd
  1109. +       ? fLogSize - fLogEnd + fLogStart
  1110. +       : fLogStart - fLogEnd;
  1111. +}
  1112. +
  1113. +
  1114. +status_t
  1115. +Journal::FlushLogAndBlocks()
  1116. +{
  1117. +   return _FlushLog(true, true);
  1118. +}
  1119. +
  1120. +
  1121. +int32
  1122. +Journal::TransactionID() const
  1123. +{
  1124. +   return fTransactionID;
  1125. +}
  1126. +
  1127. +
  1128. +status_t
  1129. +Journal::_WriteTransactionToLog()
  1130. +{
  1131. +   // Transaction enters the Flush state
  1132. +   bool detached = false;
  1133. +   size_t size = _FullTransactionSize();
  1134. +
  1135. +   if (size > fLogSize) {
  1136. +       size = _MainTransactionSize();
  1137. +
  1138. +       if(fHasSubTransaction && size < fMaxTransactionSize)
  1139. +           detached = true;
  1140. +       else {
  1141. +           // Error: transaction can't fit in log
  1142. +           panic("transaction too large (size: %d, max size: %d)\n",
  1143. +               (int)_MainTransactionSize(), (int)fLogSize);
  1144. +           return B_BUFFER_OVERFLOW;
  1145. +       }
  1146. +   }
  1147. +
  1148. +   if (size > FreeLogBlocks()) {
  1149. +       cache_sync_transaction(fFilesystemBlockCache, fTransactionID);
  1150. +
  1151. +       if (size > FreeLogBlocks()) {
  1152. +           panic("Transaction fits, but sync didn't result in enough"
  1153. +               "free space.\n\tGot %ld when at least %ld was expected.",
  1154. +               (long)FreeLogBlocks(), (long)size);
  1155. +       }
  1156. +   }
  1157. +
  1158. +   fHasSubTransaction = false;
  1159. +
  1160. +   uint32 logBlock = fLogStart + 1;
  1161. +   uint32 physicalBlock;
  1162. +   status_t status = MapBlock(logBlock, physicalBlock);
  1163. +   if (status != B_OK)
  1164. +       return status;
  1165. +
  1166. +   off_t logOffset = physicalBlock * fBlockSize;
  1167. +   off_t blockNumber;
  1168. +   long cookie = 0;
  1169. +
  1170. +   JournalHeader* blockData = NULL;
  1171. +   JournalHeader* descriptorBlock =
  1172. +       (JournalHeader*)new(std::nothrow) uint8[fBlockSize];
  1173. +   descriptorBlock->MakeDescriptor(fCurrentCommitID);
  1174. +
  1175. +   JournalBlockTag* tag = (JournalBlockTag*)descriptorBlock->data;
  1176. +   int32 blockCount = 0;
  1177. +
  1178. +   uint8* escapedData = NULL;
  1179. +   void* finalData = NULL;
  1180. +
  1181. +   // TODO: use iovecs?
  1182. +   /*int maxVecs = detached ? _MainTransactionSize() : _FullTransactionSize();
  1183. +
  1184. +   iovec* vecs = new(std::nothrow) iovecs[maxVecs];
  1185. +   if (vecs == NULL)
  1186. +       return B_NO_MEMORY;
  1187. +
  1188. +   int32 index = 0;*/
  1189. +
  1190. +   while (cache_next_block_in_transaction(fFilesystemBlockCache,
  1191. +           fTransactionID, detached, &cookie, &blockNumber,
  1192. +           &(void*)blockData, NULL) == B_OK) {
  1193. +       tag->SetBlockNumber(blockNumber);
  1194. +       tag->SetFlags(0);
  1195. +
  1196. +       if (blockData == NULL) {
  1197. +           panic("Got a NULL pointer while iterating through transaction "
  1198. +               "blocks.\n");
  1199. +           return B_ERROR;
  1200. +       }
  1201. +
  1202. +       if (blockData->CheckMagic()) {
  1203. +           // The journaled block starts with the magic value
  1204. +           // We must remove it to prevent confusion
  1205. +           tag->SetEscapedFlag();
  1206. +
  1207. +           if (escapedData == NULL) {
  1208. +               escapedData = new(std::nothrow) uint8[fBlockSize];
  1209. +               ((int32*)escapedData)[0] = 0; // Remove magic
  1210. +           }
  1211. +
  1212. +           memcpy(escapedData + 4, blockData->data, fBlockSize - 4);
  1213. +           finalData = escapedData;
  1214. +       } else
  1215. +           finalData = (void*)blockData;
  1216. +
  1217. +       size_t written = write_pos(fJournalVolume->Device(), logOffset,
  1218. +           finalData, fBlockSize);
  1219. +       if (written != fBlockSize) {
  1220. +           TRACE("Failed to write journal block.\n");
  1221. +
  1222. +           delete [] descriptorBlock;
  1223. +          
  1224. +           if (escapedData != NULL)
  1225. +               delete [] escapedData;
  1226. +
  1227. +           return B_IO_ERROR;
  1228. +       }
  1229. +
  1230. +       logBlock = _WrapAroundLog(++logBlock);
  1231. +       status = MapBlock(logBlock, physicalBlock);
  1232. +       if (status != B_OK)
  1233. +           return status;
  1234. +
  1235. +       logOffset = physicalBlock & fBlockSize;
  1236. +
  1237. +       tag++;
  1238. +       blockCount++;
  1239. +   }
  1240. +
  1241. +   // Write descriptor block
  1242. +   --tag;
  1243. +   tag->SetLastTagFlag();
  1244. +  
  1245. +   status = MapBlock(fLogStart, physicalBlock);
  1246. +   if (status != B_OK)
  1247. +       return status;
  1248. +
  1249. +   off_t startOffset = physicalBlock * fBlockSize;
  1250. +
  1251. +   size_t written = write_pos(fJournalVolume->Device(), startOffset,
  1252. +       descriptorBlock, fBlockSize);
  1253. +   if (written != fBlockSize) {
  1254. +       TRACE("Failed to write journal descriptor block.\n");
  1255. +
  1256. +       delete [] descriptorBlock;
  1257. +      
  1258. +       if (escapedData != NULL)
  1259. +           delete [] escapedData;
  1260. +
  1261. +       return B_IO_ERROR;
  1262. +   }
  1263. +  
  1264. +   // Transaction will enter the Commit state
  1265. +   JournalHeader* commitBlock = descriptorBlock;
  1266. +       // Reuse buffer
  1267. +   commitBlock->MakeCommit(fCurrentCommitID);
  1268. +   memset(commitBlock->data, 0, fBlockSize - sizeof(JournalHeader));
  1269. +       // TODO: This probably isn't necessary
  1270. +
  1271. +   written = write_pos(fJournalVolume->Device(), logOffset, commitBlock,
  1272. +       fBlockSize);
  1273. +   if (written != fBlockSize) {
  1274. +       TRACE("Failed to write journal commit block.\n");
  1275. +
  1276. +       delete [] commitBlock;
  1277. +           // Which is aslo descriptorBlock
  1278. +      
  1279. +       if (escapedData != NULL)
  1280. +           delete [] escapedData;
  1281. +
  1282. +       return B_IO_ERROR;
  1283. +   }
  1284. +  
  1285. +   fLogEnd = _WrapAroundLog(fLogEnd + blockCount);
  1286. +
  1287. +   status = _SaveSuperBlock();
  1288. +
  1289. +   delete [] commitBlock;
  1290. +       // Which is aslo descriptorBlock
  1291. +  
  1292. +   if (escapedData != NULL)
  1293. +       delete [] escapedData;
  1294. +
  1295. +   // Transaction will enter Finished state
  1296. +   blockCount += 2;    // Include descriptor and commit blocks
  1297. +   LogEntry *logEntry = new LogEntry(this, fLogEnd, fCurrentCommitID++);
  1298. +   if (logEntry == NULL) {
  1299. +       panic("no memory to allocate log entries!");
  1300. +       return B_NO_MEMORY;
  1301. +   }
  1302. +
  1303. +   mutex_lock(&fLogEntriesLock);
  1304. +   fLogEntries.Add(logEntry);
  1305. +   mutex_unlock(&fLogEntriesLock);
  1306. +
  1307. +   if (detached) {
  1308. +       fTransactionID = cache_detach_sub_transaction(fFilesystemBlockCache,
  1309. +           fTransactionID, _TransactionWritten, logEntry);
  1310. +       fUnwrittenTransactions = 1;
  1311. +
  1312. +       if (status == B_OK && _FullTransactionSize() > fLogSize) {
  1313. +           // If the transaction is too large after writing, there is no way to
  1314. +           // recover, so let this transaction fail.
  1315. +           dprintf("transaction too large (%d blocks, log size %d)!\n",
  1316. +               (int)_FullTransactionSize(), (int)fLogSize);
  1317. +           return B_BUFFER_OVERFLOW;
  1318. +       }
  1319. +   } else {
  1320. +       cache_end_transaction(fFilesystemBlockCache, fTransactionID,
  1321. +           _TransactionWritten, logEntry);
  1322. +       fUnwrittenTransactions = 0;
  1323. +   }
  1324. +
  1325. +   return B_OK;
  1326. +}
  1327. +
  1328. +
  1329. +status_t
  1330. +Journal::_SaveSuperBlock()
  1331. +{
  1332. +   uint32 physicalBlock;
  1333. +   status_t status = MapBlock(0, physicalBlock);
  1334. +   if (status != B_OK)
  1335. +       return status;
  1336. +
  1337. +   off_t superblockPos = physicalBlock * fBlockSize;
  1338. +
  1339. +   JournalSuperBlock superblock;
  1340. +   size_t bytesRead = read_pos(fJournalVolume->Device(), superblockPos,
  1341. +       &superblock, sizeof(superblock));
  1342. +
  1343. +   if (bytesRead != sizeof(superblock))
  1344. +       return B_IO_ERROR;
  1345. +
  1346. +   superblock.SetFirstCommitID(fFirstCommitID);
  1347. +   superblock.SetLogStart(fLogStart);
  1348. +  
  1349. +   size_t bytesWritten = write_pos(fJournalVolume->Device(), superblockPos,
  1350. +       &superblock, sizeof(superblock));
  1351. +
  1352. +   if (bytesWritten != sizeof(superblock))
  1353. +       return B_IO_ERROR;
  1354. +
  1355. +   return B_OK;
  1356. +}
  1357. +
  1358. +
  1359. +status_t
  1360. +Journal::_LoadSuperBlock()
  1361. +{
  1362. +   uint32 superblockPos;
  1363. +
  1364. +   status_t status = MapBlock(0, superblockPos);
  1365. +   if (status != B_OK)
  1366. +       return status;
  1367. +  
  1368. +   JournalSuperBlock superblock;
  1369. +   size_t bytesRead = read_pos(fJournalVolume->Device(), superblockPos,
  1370. +       &superblock, sizeof(superblock));
  1371. +
  1372. +   if (bytesRead != sizeof(superblock))
  1373. +       return B_IO_ERROR;
  1374. +
  1375. +   if (superblock.header.Magic() != JOURNAL_MAGIC)
  1376. +       return B_BAD_VALUE;
  1377. +
  1378. +   if (superblock.header.BlockType() == JOURNAL_SUPERBLOCK_V1)
  1379. +       fVersion = 1;
  1380. +   else if (superblock.header.BlockType() == JOURNAL_SUPERBLOCK_V2)
  1381. +       fVersion = 2;
  1382. +   else
  1383. +       return B_BAD_VALUE;
  1384. +
  1385. +   if (fVersion >= 2) {
  1386. +       status = _CheckFeatures(&superblock);
  1387. +
  1388. +       if (status != B_OK)
  1389. +           return status;
  1390. +   }
  1391. +
  1392. +   fBlockSize = superblock.BlockSize();
  1393. +   fFirstCommitID = superblock.FirstCommitID();
  1394. +   fFirstLogBlock = superblock.FirstLogBlock();
  1395. +   fLogStart = superblock.LogStart();
  1396. +   fLogSize = superblock.NumBlocks();
  1397. +   fMaxTransactionSize = superblock.MaxTransactionData();
  1398. +   //fFirstCacheCommitID = fFirstCommitID - fTransactionID /*+ 1*/;
  1399. +
  1400. +   return B_OK;
  1401. +}
  1402. +
  1403. +
  1404. +status_t
  1405. +Journal::_CheckFeatures(JournalSuperBlock* superblock)
  1406. +{
  1407. +   if ((superblock->ReadOnlyCompatibleFeatures()
  1408. +           & ~JOURNAL_KNOWN_READ_ONLY_COMPATIBLE_FEATURES) != 0
  1409. +       && (superblock->IncompatibleFeatures()
  1410. +           & ~JOURNAL_KNOWN_INCOMPATIBLE_FEATURES) != 0)
  1411. +       return B_NOT_SUPPORTED;
  1412. +
  1413. +   return B_OK;
  1414. +}
  1415. +
  1416. +
  1417. +uint32
  1418. +Journal::_CountTags(JournalHeader* descriptorBlock)
  1419. +{
  1420. +   uint32 count = 0;
  1421. +
  1422. +   JournalBlockTag* tags = (JournalBlockTag*)descriptorBlock->data;
  1423. +       // Skip the header
  1424. +   JournalBlockTag* lastTag = (JournalBlockTag*)
  1425. +       (descriptorBlock + fBlockSize - sizeof(JournalBlockTag));
  1426. +
  1427. +   while (tags < lastTag && (tags->Flags() & JOURNAL_FLAG_LAST_TAG) == 0) {
  1428. +       if ((tags->Flags() & JOURNAL_FLAG_SAME_UUID) == 0) {
  1429. +           // sizeof(UUID) = 16 = 2*sizeof(JournalBlockTag)
  1430. +           tags += 2;  // Skip new UUID
  1431. +       }
  1432. +
  1433. +       tags++; // Go to next tag
  1434. +       count++;
  1435. +   }
  1436. +
  1437. +   return count;
  1438. +}
  1439. +
  1440. +
  1441. +/*virtual*/ status_t
  1442. +Journal::Recover()
  1443. +{
  1444. +   if (fLogStart == 0) // Journal was cleanly unmounted
  1445. +       return B_OK;
  1446. +
  1447. +   uint32 lastCommitID;
  1448. +
  1449. +   status_t status = _RecoverPassScan(lastCommitID);
  1450. +   if (status != B_OK)
  1451. +       return status;
  1452. +  
  1453. +   status = _RecoverPassRevoke(lastCommitID);
  1454. +   if (status != B_OK)
  1455. +       return status;
  1456. +
  1457. +   return _RecoverPassReplay(lastCommitID);
  1458. +}
  1459. +
  1460. +
  1461. +// First pass: Find the end of the log
  1462. +status_t
  1463. +Journal::_RecoverPassScan(uint32& lastCommitID)
  1464. +{
  1465. +   TRACE("Journal Recover: 1st Pass: Scan\n");
  1466. +
  1467. +   CachedBlock cached(fJournalVolume);
  1468. +   JournalHeader* header;
  1469. +   uint32 nextCommitID = fFirstCommitID;
  1470. +   uint32 nextBlock = fLogStart;
  1471. +   uint32 nextBlockPos;
  1472. +
  1473. +   status_t status = MapBlock(nextBlock, nextBlockPos);
  1474. +   if (status != B_OK)
  1475. +       return status;
  1476. +
  1477. +   header = (JournalHeader*)cached.SetTo(nextBlockPos);
  1478. +
  1479. +   while (header->CheckMagic() && header->Sequence() == nextCommitID) {
  1480. +       uint32 blockType = header->BlockType();
  1481. +
  1482. +       if (blockType == JOURNAL_DESCRIPTOR_BLOCK)
  1483. +           nextBlock = _WrapAroundLog(nextBlock + _CountTags(header));
  1484. +       else if (blockType == JOURNAL_COMMIT_BLOCK)
  1485. +           nextCommitID++;
  1486. +       else if (blockType != JOURNAL_REVOKE_BLOCK) {
  1487. +               // TODO: Warn that we found an unrecognized block
  1488. +           break;
  1489. +       } // If blockType == JOURNAL_REVOKE_BLOCK we just skip it
  1490. +
  1491. +       nextBlock = _WrapAroundLog(nextBlock + 1);
  1492. +
  1493. +       status = MapBlock(nextBlock, nextBlockPos);
  1494. +       if (status != B_OK)
  1495. +           return status;
  1496. +
  1497. +       header = (JournalHeader*)cached.SetTo(nextBlockPos);
  1498. +   }
  1499. +
  1500. +   TRACE("Last detected transaction ID: %lu\n", nextCommitID);
  1501. +
  1502. +   lastCommitID = nextCommitID;
  1503. +   return B_OK;
  1504. +}
  1505. +
  1506. +
  1507. +// Second pass: Collect all revoked blocks
  1508. +status_t
  1509. +Journal::_RecoverPassRevoke(uint32 lastCommitID)
  1510. +{
  1511. +   TRACE("Journal Recover: 2nd Pass: Revoke\n");
  1512. +
  1513. +   CachedBlock cached(fJournalVolume);
  1514. +   JournalHeader* header;
  1515. +   uint32 nextCommitID = fFirstCommitID;
  1516. +   uint32 nextBlock = fLogStart;
  1517. +   uint32 nextBlockPos;
  1518. +
  1519. +   status_t status = MapBlock(nextBlock, nextBlockPos);
  1520. +   if (status != B_OK)
  1521. +       return status;
  1522. +
  1523. +   header = (JournalHeader*)cached.SetTo(nextBlockPos);
  1524. +
  1525. +   while (nextCommitID < lastCommitID) {
  1526. +       if (!header->CheckMagic() || header->Sequence() != nextCommitID) {
  1527. +           // Somehow the log is different than the expexted
  1528. +           return B_ERROR;
  1529. +       }
  1530. +
  1531. +       uint32 blockType = header->BlockType();
  1532. +
  1533. +       if (blockType == JOURNAL_DESCRIPTOR_BLOCK)
  1534. +           nextBlock = _WrapAroundLog(nextBlock + _CountTags(header));
  1535. +       else if (blockType == JOURNAL_COMMIT_BLOCK)
  1536. +           nextCommitID++;
  1537. +       else if (blockType == JOURNAL_REVOKE_BLOCK) {
  1538. +           status = fRevokeManager->ScanRevokeBlock(
  1539. +               (JournalRevokeHeader*)header, nextCommitID);
  1540. +
  1541. +           if (status != B_OK)
  1542. +               return status;
  1543. +       } else {
  1544. +               // TODO: Warn that we found an unrecognized block
  1545. +           break;
  1546. +       }
  1547. +
  1548. +       nextBlock = _WrapAroundLog(nextBlock + 1);
  1549. +
  1550. +       status = MapBlock(nextBlock, nextBlockPos);
  1551. +       if (status != B_OK)
  1552. +           return status;
  1553. +
  1554. +       header = (JournalHeader*)cached.SetTo(nextBlockPos);
  1555. +   }
  1556. +
  1557. +   if (nextCommitID != lastCommitID) {
  1558. +       // Possibly because of some sort of IO error
  1559. +       return B_ERROR;
  1560. +   }
  1561. +
  1562. +   TRACE("Revoked blocks: %lu\n", fRevokeManager->NumRevokes());
  1563. +
  1564. +   return B_OK;
  1565. +}
  1566. +
  1567. +
  1568. +// Third pass: Replay log
  1569. +status_t
  1570. +Journal::_RecoverPassReplay(uint32 lastCommitID)
  1571. +{
  1572. +   TRACE("Journal Recover: 3rd Pass: Replay\n");
  1573. +
  1574. +   uint32 nextCommitID = fFirstCommitID;
  1575. +   uint32 nextBlock = fLogStart;
  1576. +   uint32 nextBlockPos;
  1577. +
  1578. +   status_t status = MapBlock(nextBlock, nextBlockPos);
  1579. +   if (status != B_OK)
  1580. +       return status;
  1581. +
  1582. +   CachedBlock cached(fJournalVolume);
  1583. +   JournalHeader* header = (JournalHeader*)cached.SetTo(nextBlockPos);
  1584. +
  1585. +   int count = 0;
  1586. +
  1587. +   uint8* data = new(std::nothrow) uint8[fBlockSize];
  1588. +
  1589. +   while (nextCommitID < lastCommitID) {
  1590. +       if (!header->CheckMagic() || header->Sequence() != nextCommitID) {
  1591. +           // Somehow the log is different than the expexted
  1592. +           return B_ERROR;
  1593. +       }
  1594. +
  1595. +       uint32 blockType = header->BlockType();
  1596. +
  1597. +       if (blockType == JOURNAL_DESCRIPTOR_BLOCK) {
  1598. +           JournalBlockTag* last_tag = (JournalBlockTag*)((uint8*)header
  1599. +               + fBlockSize - sizeof(JournalBlockTag));
  1600. +
  1601. +           for (JournalBlockTag* tag = (JournalBlockTag*)header->data;
  1602. +               tag <= last_tag; ++tag) {
  1603. +               nextBlock = _WrapAroundLog(nextBlock + 1);
  1604. +
  1605. +               status = MapBlock(nextBlock, nextBlockPos);
  1606. +               if (status != B_OK) {
  1607. +                   delete [] data;
  1608. +                   return status;
  1609. +               }
  1610. +
  1611. +               size_t read = read_pos(fJournalVolume->Device(),
  1612. +                   nextBlockPos * fBlockSize, data, fBlockSize);
  1613. +               if (read != fBlockSize) {
  1614. +                   delete [] data;
  1615. +                   return B_IO_ERROR;
  1616. +               }
  1617. +
  1618. +               if (!fRevokeManager->Lookup(tag->BlockNumber(),
  1619. +                       nextCommitID)) {
  1620. +                   // Block isn't revoked
  1621. +                   if ((tag->Flags() & JOURNAL_FLAG_ESCAPED) != 0) {
  1622. +                       // Block is escaped
  1623. +                       ((int32*)data)[0]
  1624. +                           = B_HOST_TO_BENDIAN_INT32(JOURNAL_MAGIC);
  1625. +                   }
  1626. +
  1627. +                   size_t written = write_pos(fFilesystemVolume->Device(),
  1628. +                       tag->BlockNumber() * fBlockSize, data, fBlockSize);
  1629. +
  1630. +                   if (written != fBlockSize) {
  1631. +                       delete [] data;
  1632. +                       return B_IO_ERROR;
  1633. +                   }
  1634. +
  1635. +                   ++count;
  1636. +               }
  1637. +
  1638. +               if ((tag->Flags() & JOURNAL_FLAG_LAST_TAG) != 0)
  1639. +                   break;
  1640. +               if ((tag->Flags() & JOURNAL_FLAG_SAME_UUID) == 0) {
  1641. +                   // TODO: Check new UUID with file system UUID
  1642. +                   tag += 2;
  1643. +                       // sizeof(JournalBlockTag) = 8
  1644. +                       // sizeof(UUID) = 16
  1645. +               }
  1646. +           }
  1647. +       }
  1648. +       else if (blockType == JOURNAL_COMMIT_BLOCK)
  1649. +           nextCommitID++;
  1650. +       else if (blockType != JOURNAL_REVOKE_BLOCK) {
  1651. +               // TODO: Warn that we found an unrecognized block
  1652. +           break;
  1653. +       } // If blockType == JOURNAL_REVOKE_BLOCK we just skip it
  1654. +
  1655. +       nextBlock = _WrapAroundLog(nextBlock + 1);
  1656. +
  1657. +       status = MapBlock(nextBlock, nextBlockPos);
  1658. +       if (status != B_OK)
  1659. +           return status;
  1660. +
  1661. +       header = (JournalHeader*)cached.SetTo(nextBlockPos);
  1662. +   }
  1663. +
  1664. +   delete [] data;
  1665. +
  1666. +   if (nextCommitID != lastCommitID) {
  1667. +       // Possibly because of some sort of IO error
  1668. +       return B_ERROR;
  1669. +   }
  1670. +
  1671. +   TRACE("Replayed blocks: %u\n", count);
  1672. +
  1673. +   return B_OK;
  1674. +}
  1675. +
  1676. +
  1677. +status_t
  1678. +Journal::_FlushLog(bool canWait, bool flushBlocks)
  1679. +{
  1680. +   status_t status = canWait ? recursive_lock_lock(&fLock)
  1681. +       : recursive_lock_trylock(&fLock);
  1682. +   if (status != B_OK)
  1683. +       return status;
  1684. +
  1685. +   if (recursive_lock_get_recursion(&fLock) > 1) {
  1686. +       // Called from inside a transaction
  1687. +       recursive_lock_unlock(&fLock);
  1688. +       return B_OK;
  1689. +   }
  1690. +
  1691. +   if (fUnwrittenTransactions != 0 && _FullTransactionSize() != 0) {
  1692. +       status = _WriteTransactionToLog();
  1693. +       if (status < B_OK)
  1694. +           panic("Failed flushing transaction: %s\n", strerror(status));
  1695. +   }
  1696. +
  1697. +   status = fJournalVolume->FlushDevice();
  1698. +   if (status != B_OK)
  1699. +       return status;
  1700. +
  1701. +   if (flushBlocks)
  1702. +       status = fFilesystemVolume->FlushDevice();
  1703. +
  1704. +   recursive_lock_unlock(&fLock);
  1705. +   return status;
  1706. +}
  1707. +
  1708. +
  1709. +inline uint32
  1710. +Journal::_WrapAroundLog(uint32 block)
  1711. +{
  1712. +   if (block >= fLogSize)
  1713. +       return block - fLogSize + fLogStart;
  1714. +   else
  1715. +       return block;
  1716. +}
  1717. +
  1718. +
  1719. +size_t
  1720. +Journal::_CurrentTransactionSize() const
  1721. +{
  1722. +   return fHasSubTransaction
  1723. +       ? cache_blocks_in_sub_transaction(fFilesystemBlockCache,
  1724. +           fTransactionID)
  1725. +       : cache_blocks_in_transaction(fFilesystemBlockCache, fTransactionID);
  1726. +}
  1727. +
  1728. +
  1729. +size_t
  1730. +Journal::_FullTransactionSize() const
  1731. +{
  1732. +   return cache_blocks_in_transaction(fFilesystemBlockCache, fTransactionID);
  1733. +}
  1734. +
  1735. +
  1736. +size_t
  1737. +Journal::_MainTransactionSize() const
  1738. +{
  1739. +   return cache_blocks_in_main_transaction(fFilesystemBlockCache,
  1740. +       fTransactionID);
  1741. +}
  1742. +
  1743. +
  1744. +status_t
  1745. +Journal::_TransactionDone(bool success)
  1746. +{
  1747. +   if (!success) {
  1748. +       if (fHasSubTransaction) {
  1749. +           cache_abort_sub_transaction(fFilesystemBlockCache, fTransactionID);
  1750. +           // parent is unaffected
  1751. +       } else {
  1752. +           cache_abort_transaction(fFilesystemBlockCache, fTransactionID);
  1753. +           fUnwrittenTransactions = 0;
  1754. +       }
  1755. +
  1756. +       return B_OK;
  1757. +   }
  1758. +  
  1759. +   // If possible, delay flushing the transaction
  1760. +   uint32 size = _FullTransactionSize();
  1761. +   if (size < fMaxTransactionSize) {
  1762. +       // Make sure the transaction fits in the log
  1763. +       if (size < FreeLogBlocks())
  1764. +           cache_sync_transaction(fFilesystemBlockCache, fTransactionID);
  1765. +      
  1766. +       fUnwrittenTransactions++;
  1767. +       return B_OK;
  1768. +   }
  1769. +
  1770. +   return _WriteTransactionToLog();
  1771. +}
  1772. +
  1773. +
  1774. +/*static*/ void
  1775. +Journal::_TransactionWritten(int32 transactionID, int32 event, void* _logEntry)
  1776. +{
  1777. +   LogEntry* logEntry = (LogEntry*)_logEntry;
  1778. +
  1779. +   TRACE("Transaction finished. ID: %lu\n", transactionID);
  1780. +
  1781. +   Journal* journal = logEntry->GetJournal();
  1782. +
  1783. +   mutex_lock(&journal->fLogEntriesLock);
  1784. +
  1785. +   if (logEntry == journal->fLogEntries.First()) {
  1786. +       LogEntry* next = journal->fLogEntries.GetNext(logEntry);
  1787. +       if (next != NULL)
  1788. +           journal->fLogStart = next->Start();
  1789. +       else {
  1790. +           journal->fLogStart = journal->fLogEnd;
  1791. +           journal->fFirstCommitID = next->CommitID();
  1792. +       }
  1793. +
  1794. +       journal->_SaveSuperBlock();
  1795. +           // TODO: What if this fails?
  1796. +   }
  1797. +
  1798. +   journal->fLogEntries.Remove(logEntry);
  1799. +   mutex_unlock(&journal->fLogEntriesLock);
  1800. +
  1801. +   delete logEntry;
  1802. +}
  1803. +
  1804. +
  1805. +/*static*/ void
  1806. +Journal::_TransactionIdle(int32 transactionID, int32 event, void* _journal)
  1807. +{
  1808. +   Journal* journal = (Journal*)_journal;
  1809. +   journal->_FlushLog(false, false);
  1810. +}
  1811.  
  1812. Property changes on: src/add-ons/kernel/file_systems/ext2/Journal.cpp
  1813. ___________________________________________________________________
  1814. Added: svn:executable
  1815.    + *
  1816.  
  1817. Index: src/add-ons/kernel/file_systems/ext2/NoJournal.h
  1818. ===================================================================
  1819. --- src/add-ons/kernel/file_systems/ext2/NoJournal.h    (revision 0)
  1820. +++ src/add-ons/kernel/file_systems/ext2/NoJournal.h    (revision 0)
  1821. @@ -0,0 +1,30 @@
  1822. +/*
  1823. + * Copyright 2001-2010, Haiku Inc. All rights reserved.
  1824. + * This file may be used under the terms of the MIT License.
  1825. + *
  1826. + * Authors:
  1827. + *     Janito V. Ferreira Filho
  1828. + */
  1829. +#ifndef NOJOURNAL_H
  1830. +#define NOJOURNAL_H
  1831. +
  1832. +
  1833. +#include "Journal.h"
  1834. +
  1835. +
  1836. +class NoJournal : public Journal {
  1837. +public:
  1838. +                       NoJournal(Volume* volume);
  1839. +                       ~NoJournal();
  1840. +
  1841. +           status_t    InitCheck();
  1842. +           status_t    Recover();
  1843. +           status_t    StartLog();
  1844. +private:
  1845. +           status_t    _WriteTransactionToLog();
  1846. +
  1847. +   static  void        _TransactionWritten(int32 transactionID,
  1848. +                           int32 event, void* param);
  1849. +};
  1850. +
  1851. +#endif // NOJOURNAL_H
  1852.  
  1853. Property changes on: src/add-ons/kernel/file_systems/ext2/HTree.h
  1854. ___________________________________________________________________
  1855. Added: svn:executable
  1856.    + *
  1857.  
  1858. Index: src/add-ons/kernel/file_systems/ext2/IndexedDirectoryIterator.cpp
  1859. ===================================================================
  1860. --- src/add-ons/kernel/file_systems/ext2/IndexedDirectoryIterator.cpp   (revision 37473)
  1861. +++ src/add-ons/kernel/file_systems/ext2/IndexedDirectoryIterator.cpp   (working copy)
  1862. @@ -24,17 +24,16 @@
  1863.  
  1864.  
  1865.  IndexedDirectoryIterator::IndexedDirectoryIterator(off_t start,
  1866. -   uint32 blockSize, Inode* directory, HTreeEntryIterator* parent)
  1867. +   Inode* directory, HTreeEntryIterator* parent)
  1868.     :
  1869.     DirectoryIterator(directory),
  1870.     fIndexing(true),
  1871. -  
  1872.     fParent(parent),
  1873. -   fMaxOffset(start + blockSize),
  1874. -   fBlockSize(blockSize),
  1875.     fMaxAttempts(0)
  1876.  {
  1877. -   fOffset = start;
  1878. +   fDisplacement = start % fBlockSize;
  1879. +   fInitStatus = fInode->FindBlock(start / fBlockSize, fBlock);
  1880. +   fPreviousBlock = fBlock;
  1881.  }
  1882.  
  1883.  
  1884. @@ -46,16 +45,20 @@
  1885.  status_t
  1886.  IndexedDirectoryIterator::GetNext(char* name, size_t* nameLength, ino_t* id)
  1887.  {
  1888. -   if (fIndexing && fOffset + sizeof(HTreeFakeDirEntry) >= fMaxOffset) {
  1889. +   if (fIndexing && fBlock != fPreviousBlock) {
  1890.         TRACE("IndexedDirectoryIterator::GetNext() calling next block\n");
  1891. -       status_t status = fParent->GetNext(fOffset);
  1892. +
  1893. +       // TODO: If parent doesn't have collisions, the entry wasn't found
  1894. +
  1895. +       fDisplacement = 0;
  1896. +       status_t status = fParent->GetNext(fBlock);
  1897.         if (status != B_OK)
  1898.             return status;
  1899.  
  1900. +       fPreviousBlock = fBlock;
  1901. +
  1902.         if (fMaxAttempts++ > 4)
  1903.             return B_ERROR;
  1904. -      
  1905. -       fMaxOffset = fOffset + fBlockSize;
  1906.     }
  1907.    
  1908.     return DirectoryIterator::GetNext(name, nameLength, id);
  1909. @@ -67,9 +70,23 @@
  1910.  {
  1911.     // The only way to rewind it is too loose indexing
  1912.    
  1913. -   fOffset = 0;
  1914. -   fMaxOffset = fInode->Size();
  1915. +   fDisplacement = 0;
  1916.     fIndexing = false;
  1917.  
  1918. -   return B_OK;
  1919. +   return fInode->FindBlock(0, fBlock);
  1920.  }
  1921. +
  1922. +
  1923. +status_t
  1924. +IndexedDirectoryIterator::AddEntry(Transaction& transaction, char* name,
  1925. +   size_t _nameLength, ino_t id)
  1926. +{
  1927. +   panic("Adding entries to a HTree is not supported yet.\n");
  1928. +
  1929. +   // TODO: Once the method DirectoryIterator::FindEmptyEntrySpot is
  1930. +   // implemented, we should call it to see if the offset exceeds the
  1931. +   // fMaxOffset. If it does, the current block is full, and we need
  1932. +   // to start splitting nodes.
  1933. +  
  1934. +   return B_NOT_SUPPORTED;
  1935. +}
  1936. Index: src/add-ons/kernel/file_systems/ext2/DirectoryIterator.h
  1937. ===================================================================
  1938. --- src/add-ons/kernel/file_systems/ext2/DirectoryIterator.h    (revision 37473)
  1939. +++ src/add-ons/kernel/file_systems/ext2/DirectoryIterator.h    (working copy)
  1940. @@ -8,7 +8,9 @@
  1941.  
  1942.  #include <SupportDefs.h>
  1943.  
  1944. +#include "Transaction.h"
  1945.  
  1946. +
  1947.  class Inode;
  1948.  
  1949.  class DirectoryIterator {
  1950. @@ -16,10 +18,15 @@
  1951.                         DirectoryIterator(Inode* inode);
  1952.     virtual             ~DirectoryIterator();
  1953.  
  1954. +   virtual status_t    InitCheck();
  1955. +
  1956.     virtual status_t    GetNext(char* name, size_t* _nameLength, ino_t* id);
  1957.  
  1958.     virtual status_t    Rewind();
  1959.  
  1960. +   virtual status_t    AddEntry(Transaction& transaction, char* name,
  1961. +                           size_t nameLength, ino_t id);
  1962. +
  1963.  private:
  1964.                         DirectoryIterator(const DirectoryIterator&);
  1965.                         DirectoryIterator &operator=(const DirectoryIterator&);
  1966. @@ -27,7 +34,11 @@
  1967.  
  1968.  protected:
  1969.     Inode*              fInode;
  1970. -   off_t               fOffset;
  1971. +   uint32              fBlock;
  1972. +   uint32              fDisplacement;
  1973. +   uint32              fBlockSize;
  1974. +   status_t            fInitStatus;
  1975.  };
  1976.  
  1977.  #endif // DIRECTORY_ITERATOR_H
  1978. +
  1979. Index: src/add-ons/kernel/file_systems/ext2/RevokeManager.cpp
  1980. ===================================================================
  1981. --- src/add-ons/kernel/file_systems/ext2/RevokeManager.cpp  (revision 0)
  1982. +++ src/add-ons/kernel/file_systems/ext2/RevokeManager.cpp  (revision 0)
  1983. @@ -0,0 +1,38 @@
  1984. +/*
  1985. + * Copyright 2001-2010, Haiku Inc. All rights reserved.
  1986. + * This file may be used under the terms of the MIT License.
  1987. + *
  1988. + * Authors:
  1989. + *     Janito V. Ferreira Filho
  1990. + */
  1991. +
  1992. +#include "RevokeManager.h"
  1993. +
  1994. +
  1995. +RevokeManager::RevokeManager()
  1996. +   :
  1997. +   fRevokeCount(0)
  1998. +{
  1999. +}
  2000. +
  2001. +
  2002. +RevokeManager::~RevokeManager()
  2003. +{
  2004. +}
  2005. +
  2006. +
  2007. +status_t
  2008. +RevokeManager::ScanRevokeBlock(JournalRevokeHeader* revokeBlock, uint32 commitID)
  2009. +{
  2010. +   int count = revokeBlock->NumBytes() >> 3;
  2011. +  
  2012. +   for (int i = 0; i < count; ++i) {
  2013. +       status_t status = Insert(revokeBlock->RevokeBlock(i), commitID);
  2014. +      
  2015. +       if (status != B_OK)
  2016. +           return status;
  2017. +   }
  2018. +
  2019. +   return B_OK;
  2020. +}
  2021. +
  2022.  
  2023. Property changes on: src/add-ons/kernel/file_systems/ext2/RevokeManager.cpp
  2024. ___________________________________________________________________
  2025. Added: svn:executable
  2026.    + *
  2027.  
  2028. Index: src/add-ons/kernel/file_systems/ext2/Jamfile
  2029. ===================================================================
  2030. --- src/add-ons/kernel/file_systems/ext2/Jamfile    (revision 37473)
  2031. +++ src/add-ons/kernel/file_systems/ext2/Jamfile    (working copy)
  2032. @@ -18,6 +18,15 @@
  2033.     IndexedDirectoryIterator.cpp
  2034.     HTree.cpp
  2035.     HTreeEntryIterator.cpp
  2036. +   RevokeManager.cpp
  2037. +   HashRevokeManager.cpp
  2038. +   Journal.cpp
  2039. +   NoJournal.cpp
  2040. +   InodeJournal.cpp
  2041. +   Transaction.cpp
  2042. +   BitmapBlock.cpp
  2043. +   BlockAllocator.cpp
  2044. +   InodeAllocator.cpp
  2045.  
  2046.     kernel_interface.cpp
  2047.  ;
  2048. Index: src/add-ons/kernel/file_systems/ext2/BitmapBlock.cpp
  2049. ===================================================================
  2050. --- src/add-ons/kernel/file_systems/ext2/BitmapBlock.cpp    (revision 0)
  2051. +++ src/add-ons/kernel/file_systems/ext2/BitmapBlock.cpp    (revision 0)
  2052. @@ -0,0 +1,509 @@
  2053. +/*
  2054. + * Copyright 2001-2010, Haiku Inc. All rights reserved.
  2055. + * This file may be used under the terms of the MIT License.
  2056. + *
  2057. + * Authors:
  2058. + *     Janito V. Ferreira Filho
  2059. + */
  2060. +
  2061. +#include "BitmapBlock.h"
  2062. +
  2063. +
  2064. +BitmapBlock::BitmapBlock(Volume* volume, uint32 numBits)
  2065. +   :
  2066. +   CachedBlock(volume),
  2067. +   fData(NULL),
  2068. +   fReadOnlyData(NULL),
  2069. +   fNumBits(numBits)
  2070. +{
  2071. +}
  2072. +
  2073. +
  2074. +BitmapBlock::~BitmapBlock()
  2075. +{
  2076. +}
  2077. +
  2078. +
  2079. +/*virtual*/ bool
  2080. +BitmapBlock::SetTo(uint32 block)
  2081. +{
  2082. +   fData = NULL;
  2083. +   fReadOnlyData = (uint32*)CachedBlock::SetTo(block);
  2084. +
  2085. +   return fReadOnlyData != NULL;
  2086. +}
  2087. +
  2088. +
  2089. +/*virtual*/ bool
  2090. +BitmapBlock::SetToWritable(Transaction& transaction, uint32 block, bool empty)
  2091. +{
  2092. +   fReadOnlyData = NULL;
  2093. +   fData = (uint32*)CachedBlock::SetToWritable(transaction, block, empty);
  2094. +
  2095. +   return fData != NULL;
  2096. +}
  2097. +
  2098. +
  2099. +/*virtual*/ bool
  2100. +BitmapBlock::CheckUnmarked(uint32 start, uint32 length)
  2101. +{
  2102. +   const uint32* data = fData == NULL ? fReadOnlyData : fData;
  2103. +   if (data == NULL)
  2104. +       return false;
  2105. +
  2106. +   if (start + length > fNumBits)
  2107. +       return false;
  2108. +
  2109. +   uint32 startIndex = start >> 5;
  2110. +   uint32 startBit = start & 0x1F;
  2111. +   uint32 iterations = (length - startBit) >> 5;
  2112. +   uint32 remainingBits = (length - startBit) & 0x1F;
  2113. +
  2114. +   uint32 index = startIndex;
  2115. +   uint32 mask = 0;
  2116. +
  2117. +   if (startBit != 0) {
  2118. +       mask = ~((1 << startBit) - 1);
  2119. +       uint32 bits = B_LENDIAN_TO_HOST_INT32(data[index]);
  2120. +
  2121. +       if ((bits & mask) != 0)
  2122. +           return false;
  2123. +
  2124. +       index += 1;
  2125. +   }
  2126. +
  2127. +   for (; iterations > 0; --iterations) {
  2128. +       if (data[index++] != 0)
  2129. +           return false;
  2130. +   }
  2131. +
  2132. +   if (remainingBits != 0) {
  2133. +       mask = (1 << remainingBits + 1) - 1;
  2134. +
  2135. +       uint32 bits = B_LENDIAN_TO_HOST_INT32(data[index]);
  2136. +       if ((bits & mask) != 0)
  2137. +           return false;
  2138. +   }
  2139. +
  2140. +   return true;
  2141. +}
  2142. +
  2143. +
  2144. +/*virtual*/ bool
  2145. +BitmapBlock::CheckMarked(uint32 start, uint32 length)
  2146. +{
  2147. +   const uint32* data = fData == NULL ? fReadOnlyData : fData;
  2148. +   if (data == NULL)
  2149. +       return false;
  2150. +
  2151. +   if (start + length > fNumBits)
  2152. +       return false;
  2153. +
  2154. +   uint32 startIndex = start >> 5;
  2155. +   uint32 startBit = start & 0x1F;
  2156. +   uint32 iterations = (length - startBit) >> 5;
  2157. +   uint32 remainingBits = (length - startBit) & 0x1F;
  2158. +
  2159. +   uint32 index = startIndex;
  2160. +   uint32 mask = 0;
  2161. +
  2162. +   if (startBit != 0) {
  2163. +       mask = ~((1 << startBit) - 1);
  2164. +       uint32 bits = B_LENDIAN_TO_HOST_INT32(data[index]);
  2165. +
  2166. +       if ((bits & mask) != mask)
  2167. +           return false;
  2168. +
  2169. +       index += 1;
  2170. +   }
  2171. +
  2172. +   mask = 0xFFFFFFFF;
  2173. +   for (; iterations > 0; --iterations) {
  2174. +       if (data[index++] != mask)
  2175. +           return false;
  2176. +   }
  2177. +
  2178. +   if (remainingBits != 0) {
  2179. +       mask = (1 << remainingBits + 1) - 1;
  2180. +       uint32 bits = B_HOST_TO_LENDIAN_INT32(data[index]);
  2181. +
  2182. +       if ((bits & mask) != mask)
  2183. +           return false;
  2184. +   }
  2185. +
  2186. +   return true;
  2187. +}
  2188. +
  2189. +
  2190. +/*virtual*/ bool
  2191. +BitmapBlock::Mark(uint32 start, uint32 length, bool force)
  2192. +{
  2193. +   if (fData != NULL && start + length <= fNumBits)
  2194. +       return false;
  2195. +
  2196. +   uint32 startIndex = start >> 5;
  2197. +   uint32 startBit = start & 0x1F;
  2198. +   uint32 iterations = (length - startBit) >> 5;
  2199. +   uint32 remainingBits = (length - startBit) & 0x1F;
  2200. +
  2201. +   uint32 index = startIndex;
  2202. +   uint32 mask = 0;
  2203. +
  2204. +   if (startBit != 0) {
  2205. +       mask = ~((1 << startBit) - 1);
  2206. +       uint32 bits = B_LENDIAN_TO_HOST_INT32(fData[index]);
  2207. +
  2208. +       if (!force && (bits & mask) != 0)
  2209. +           return false;
  2210. +
  2211. +       bits |= mask;
  2212. +       fData[index] = B_HOST_TO_LENDIAN_INT32(bits);
  2213. +
  2214. +       index += 1;
  2215. +   }
  2216. +
  2217. +   mask = 0xFFFFFFFF;
  2218. +   for (; iterations > 0; --iterations) {
  2219. +       if (!force && fData[startIndex] != 0)
  2220. +           return false;
  2221. +       fData[index++] |= mask;
  2222. +   }
  2223. +
  2224. +   if (remainingBits != 0) {
  2225. +       mask = (1 << remainingBits + 1) - 1;
  2226. +       uint32 bits = B_LENDIAN_TO_HOST_INT32(fData[index]);
  2227. +
  2228. +       if (!force && (bits & mask) != 0)
  2229. +           return false;
  2230. +
  2231. +       bits |= mask;
  2232. +       fData[index] = B_HOST_TO_LENDIAN_INT32(bits);
  2233. +   }
  2234. +
  2235. +   return true;
  2236. +}
  2237. +
  2238. +
  2239. +/*virtual*/ bool
  2240. +BitmapBlock::Unmark(uint32 start, uint32 length, bool force)
  2241. +{
  2242. +   if (fData != NULL && start + length <= fNumBits)
  2243. +       return false;
  2244. +
  2245. +   uint32 startIndex = start >> 5;
  2246. +   uint32 startBit = start & 0x1F;
  2247. +   uint32 iterations = (length - startBit) >> 5;
  2248. +   uint32 remainingBits = (length - startBit) & 0x1F;
  2249. +
  2250. +   uint32 index = startIndex;
  2251. +   uint32 mask = 0;
  2252. +
  2253. +   if (startBit != 0) {
  2254. +       mask = ~((1 << startBit) - 1);
  2255. +       uint32 bits = B_LENDIAN_TO_HOST_INT32(fData[index]);
  2256. +
  2257. +       if (!force && (bits & mask) != mask)
  2258. +           return false;
  2259. +
  2260. +       bits &= ~mask;
  2261. +       fData[index] = B_HOST_TO_LENDIAN_INT32(bits);
  2262. +
  2263. +       index += 1;
  2264. +   }
  2265. +
  2266. +   mask = 0xFFFFFFFF;
  2267. +   for (; iterations > 0; --iterations) {
  2268. +       if (!force && fData[startIndex] != mask)
  2269. +           return false;
  2270. +       fData[index++] = 0;
  2271. +   }
  2272. +
  2273. +   if (remainingBits != 0) {
  2274. +       mask = (1 << remainingBits + 1) - 1;
  2275. +       uint32 bits = B_LENDIAN_TO_HOST_INT32(fData[index]);
  2276. +
  2277. +       if (!force && (bits & mask) != mask)
  2278. +           return false;
  2279. +
  2280. +       bits &= ~mask;
  2281. +       fData[index] = B_HOST_TO_LENDIAN_INT32(bits);
  2282. +   }
  2283. +
  2284. +   return true;
  2285. +}
  2286. +
  2287. +
  2288. +void
  2289. +BitmapBlock::FindNextMarked(uint32& pos)
  2290. +{
  2291. +   const uint32* data = fData == NULL ? fReadOnlyData : fData;
  2292. +   if (data == NULL)
  2293. +       return;
  2294. +
  2295. +   if (pos >= fNumBits) {
  2296. +       pos = fNumBits;
  2297. +       return;
  2298. +   }
  2299. +
  2300. +   uint32 index = pos >> 5;
  2301. +   uint32 bit = pos & 0x1F;
  2302. +
  2303. +   uint32 mask = (1 << bit) - 1;
  2304. +   uint32 bits = B_LENDIAN_TO_HOST_INT32(data[index]);
  2305. +   bits = bits & ~mask;
  2306. +
  2307. +   if (bits == 0) {
  2308. +       // Find an block of 32 bits that has a marked bit
  2309. +       uint32 maxIndex = fNumBits >> 5;
  2310. +
  2311. +       do { index++; }
  2312. +           while (data[index] == 0 && index < maxIndex);
  2313. +
  2314. +       bits = B_LENDIAN_TO_HOST_INT32(data[index]);
  2315. +       if (bits == 0) {
  2316. +           // Not found
  2317. +           pos = fNumBits;
  2318. +           return;
  2319. +       }
  2320. +
  2321. +       bit = 0;
  2322. +   }
  2323. +
  2324. +   for (; bit < 32; ++bit) {
  2325. +       // Find the marked bit
  2326. +       if ((bits >> bit & 1) != 0) {
  2327. +           pos = index << 5 | bit;
  2328. +           return;
  2329. +       }
  2330. +   }
  2331. +
  2332. +   panic("Couldn't find marked bit inside an int32 which is different than "
  2333. +       "zero!?\n");
  2334. +}
  2335. +
  2336. +
  2337. +void
  2338. +BitmapBlock::FindNextUnmarked(uint32& pos)
  2339. +{
  2340. +   const uint32* data = fData == NULL ? fReadOnlyData : fData;
  2341. +   if (data == NULL)
  2342. +       return;
  2343. +
  2344. +   if (pos >= fNumBits) {
  2345. +       pos = fNumBits;
  2346. +       return;
  2347. +   }
  2348. +
  2349. +   uint32 index = pos >> 5;
  2350. +   uint32 bit = pos & 0x1F;
  2351. +
  2352. +   uint32 mask = (1 << bit) - 1;
  2353. +   uint32 bits = B_LENDIAN_TO_HOST_INT32(data[index]);
  2354. +   bits &= ~mask;
  2355. +
  2356. +   if (bits == ~mask) {
  2357. +       // Find an block of 32 bits that has a unmarked bit
  2358. +       uint32 maxIndex = fNumBits >> 5;
  2359. +
  2360. +       do { index++; }
  2361. +           while (data[index] != 0 && index < maxIndex);
  2362. +
  2363. +       bits = B_LENDIAN_TO_HOST_INT32(data[index]);
  2364. +       if (bits != 0) {
  2365. +           // Not found
  2366. +           pos = fNumBits;
  2367. +           return;
  2368. +       }
  2369. +
  2370. +       bit = 0;
  2371. +   }
  2372. +
  2373. +   for (; bit < 32; ++bit) {
  2374. +       // Find the unmarked bit
  2375. +       if ((bits >> bit & 1) == 0) {
  2376. +           pos = index << 5 | bit;
  2377. +           return;
  2378. +       }
  2379. +   }
  2380. +
  2381. +   panic("Couldn't find unmarked bit inside an int32 whith value zero!?\n");
  2382. +}
  2383. +
  2384. +
  2385. +void
  2386. +BitmapBlock::FindPreviousMarked(uint32& pos)
  2387. +{
  2388. +   const uint32* data = fData == NULL ? fReadOnlyData : fData;
  2389. +   if (data == NULL)
  2390. +       return;
  2391. +
  2392. +   if (pos >= fNumBits)
  2393. +       pos = fNumBits;
  2394. +
  2395. +   if (pos == 0)
  2396. +       return;
  2397. +
  2398. +   uint32 index = pos >> 5;
  2399. +   uint32 bit = pos & 0x1F;
  2400. +
  2401. +   uint32 mask = (1 << bit + 1) - 1;
  2402. +   uint32 bits = B_LENDIAN_TO_HOST_INT32(data[index]);
  2403. +   bits = bits & mask;
  2404. +
  2405. +   if (bits == 0) {
  2406. +       // Find an block of 32 bits that has a marked bit
  2407. +       do { index--; }
  2408. +           while (data[index] == 0 && index >= 0);
  2409. +
  2410. +       bits = B_LENDIAN_TO_HOST_INT32(data[index]);
  2411. +       if (bits == 0) {
  2412. +           // Not found
  2413. +           pos = 0;
  2414. +           return;
  2415. +       }
  2416. +
  2417. +       bit = 31;
  2418. +   }
  2419. +
  2420. +   for (; bit >= 0; --bit) {
  2421. +       // Find the unmarked bit
  2422. +       if ((bits >> bit & 1) == 0) {
  2423. +           pos = index << 5 | bit;
  2424. +           return;
  2425. +       }
  2426. +   }
  2427. +
  2428. +   panic("Couldn't find marked bit inside an int32 whith value different than "
  2429. +       "zero!?\n");
  2430. +}
  2431. +
  2432. +
  2433. +void
  2434. +BitmapBlock::FindLargestUnmarkedRange(uint32& start, uint32& length)
  2435. +{
  2436. +   const uint32* data = fData == NULL ? fReadOnlyData : fData;
  2437. +   if (data == NULL)
  2438. +       return;
  2439. +
  2440. +   uint32 wordSpan = length >> 5;
  2441. +   uint32 lastIndex = fNumBits >> 5;
  2442. +   uint32 startIndex = 0;
  2443. +   uint32 index = 0;
  2444. +   uint32 bits = B_LENDIAN_TO_HOST_INT32(data[0]);
  2445. +
  2446. +   if (wordSpan == 0) {
  2447. +       uint32 startPos = 0;
  2448. +       uint32 endPos = 0;
  2449. +
  2450. +       while (endPos < fNumBits) {
  2451. +           FindNextUnmarked(startPos);
  2452. +           endPos = startPos;
  2453. +
  2454. +           if (startPos != fNumBits) {
  2455. +               FindNextMarked(endPos);
  2456. +               if (endPos - startPos >= 32)
  2457. +                   break;
  2458. +               else if (endPos - startPos > length) {
  2459. +                   start = startPos;
  2460. +                   length = endPos - startPos;
  2461. +               }
  2462. +
  2463. +               startPos = endPos;
  2464. +           }
  2465. +       }
  2466. +
  2467. +       if (endPos - startPos < 32) {
  2468. +           if (endPos - startPos > length) {
  2469. +               start = startPos;
  2470. +               length = endPos - startPos;
  2471. +           }
  2472. +
  2473. +           return;
  2474. +       }
  2475. +
  2476. +       start = startPos;
  2477. +       length = endPos - startPos;
  2478. +
  2479. +       wordSpan = length >> 5;
  2480. +       startIndex = startPos >> 5;
  2481. +       index = (endPos >> 5) + 1;
  2482. +       bits = B_LENDIAN_TO_HOST_INT32(data[index]);
  2483. +   }
  2484. +
  2485. +   for (; index < lastIndex; ++index) {
  2486. +       bits = B_LENDIAN_TO_HOST_INT32(data[index]);
  2487. +
  2488. +       if (bits != 0) {
  2489. +           // Contains marked bits
  2490. +           if (index - startIndex >= wordSpan) {
  2491. +               uint32 newLength = index - startIndex << 5;
  2492. +               uint32 newStart = startIndex + 1 << 5;
  2493. +
  2494. +               if (newStart != 0) {
  2495. +                   uint32 startBits =
  2496. +                       B_LENDIAN_TO_HOST_INT32(data[startIndex]);
  2497. +
  2498. +                   for (int32 bit = 31; bit >= 0; --bit) {
  2499. +                       if ((startBits >> bit & 1) != 0)
  2500. +                           break;
  2501. +
  2502. +                       ++newLength;
  2503. +                       --newStart;
  2504. +                   }
  2505. +               }
  2506. +
  2507. +               for (int32 bit = 0; bit < 32; ++bit) {
  2508. +                   if ((bits >> bit & 1) != 0)
  2509. +                       break;
  2510. +
  2511. +                   ++newLength;
  2512. +               }
  2513. +
  2514. +               if (newLength > length) {
  2515. +                   start = newStart;
  2516. +                   length = newLength;
  2517. +                   wordSpan = length >> 5;
  2518. +               }
  2519. +           }
  2520. +
  2521. +           startIndex = index;
  2522. +       }
  2523. +   }
  2524. +
  2525. +   if (index - startIndex >= wordSpan) {
  2526. +       uint32 newLength = index - startIndex << 5;
  2527. +       uint32 newStart = startIndex + 1 << 5;
  2528. +
  2529. +       if (newStart != 0) {
  2530. +           uint32 startBits = B_LENDIAN_TO_HOST_INT32(data[startIndex]);
  2531. +
  2532. +           for (int32 bit = 31; bit >= 0; --bit) {
  2533. +               if ((startBits >> bit & 1) != 0)
  2534. +                   break;
  2535. +
  2536. +               ++newLength;
  2537. +               --newStart;
  2538. +           }
  2539. +       }
  2540. +
  2541. +       for (int32 bit = 0; bit < 32; ++bit) {
  2542. +           if ((bits >> bit & 1) != 0)
  2543. +               break;
  2544. +
  2545. +           ++newLength;
  2546. +       }
  2547. +
  2548. +       if (newLength > length) {
  2549. +           start = newStart;
  2550. +           length = newLength;
  2551. +           wordSpan = length >> 5;
  2552. +       }
  2553. +   }
  2554. +}
  2555. +
  2556. +
  2557. +uint32
  2558. +BitmapBlock::NumBits() const
  2559. +{
  2560. +   return fNumBits;
  2561. +}
  2562.  
  2563. Property changes on: src/add-ons/kernel/file_systems/ext2/BitmapBlock.cpp
  2564. ___________________________________________________________________
  2565. Added: svn:executable
  2566.    + *
  2567.  
  2568. Index: src/add-ons/kernel/file_systems/ext2/InodeJournal.cpp
  2569. ===================================================================
  2570. --- src/add-ons/kernel/file_systems/ext2/InodeJournal.cpp   (revision 0)
  2571. +++ src/add-ons/kernel/file_systems/ext2/InodeJournal.cpp   (revision 0)
  2572. @@ -0,0 +1,40 @@
  2573. +/*
  2574. + * Copyright 2001-2010, Haiku Inc. All rights reserved.
  2575. + * This file may be used under the terms of the MIT License.
  2576. + *
  2577. + * Authors:
  2578. + *     Janito V. Ferreira Filho
  2579. + */
  2580. +
  2581. +#include "InodeJournal.h"
  2582. +
  2583. +#include <fs_cache.h>
  2584. +
  2585. +
  2586. +InodeJournal::InodeJournal(Inode* inode)
  2587. +   :
  2588. +   Journal(inode->GetVolume(), inode->GetVolume()),
  2589. +   fInode(inode)
  2590. +{
  2591. +   if (!inode->IsFileCacheDisabled())
  2592. +       fInitStatus = inode->DisableFileCache();
  2593. +}
  2594. +
  2595. +
  2596. +InodeJournal::~InodeJournal()
  2597. +{
  2598. +}
  2599. +
  2600. +
  2601. +status_t
  2602. +InodeJournal::InitCheck()
  2603. +{
  2604. +   return fInitStatus;
  2605. +}
  2606. +
  2607. +
  2608. +status_t
  2609. +InodeJournal::MapBlock(uint32 logical, uint32& physical)
  2610. +{
  2611. +   return fInode->FindBlock(logical * fBlockSize, physical);
  2612. +}
  2613. Index: src/add-ons/kernel/file_systems/ext2/Transaction.h
  2614. ===================================================================
  2615. --- src/add-ons/kernel/file_systems/ext2/Transaction.h  (revision 0)
  2616. +++ src/add-ons/kernel/file_systems/ext2/Transaction.h  (revision 0)
  2617. @@ -0,0 +1,72 @@
  2618. +/*
  2619. + * Copyright 2001-2010, Haiku Inc. All rights reserved.
  2620. + * This file may be used under the terms of the MIT License.
  2621. + *
  2622. + * Authors:
  2623. + *     Janito V. Ferreira Filho
  2624. + */
  2625. +#ifndef TRANSACTION_H
  2626. +#define TRANSACTION_H
  2627. +
  2628. +
  2629. +#include <util/DoublyLinkedList.h>
  2630. +
  2631. +
  2632. +class Journal;
  2633. +class Volume;
  2634. +
  2635. +
  2636. +class TransactionListener
  2637. +   : public DoublyLinkedListLinkImpl<TransactionListener> {
  2638. +public:
  2639. +                               TransactionListener();
  2640. +   virtual                     ~TransactionListener();
  2641. +
  2642. +   virtual void                TransactionDone(bool success) = 0;
  2643. +   virtual void                RemovedFromTransaction() = 0;
  2644. +};
  2645. +
  2646. +typedef DoublyLinkedList<TransactionListener> TransactionListeners;
  2647. +
  2648. +
  2649. +class Transaction {
  2650. +public:
  2651. +                                   Transaction();
  2652. +                                   Transaction(Journal* journal);
  2653. +                                   ~Transaction();
  2654. +
  2655. +           status_t                Start(Journal* journal);
  2656. +           status_t                Done();
  2657. +
  2658. +           bool                    IsStarted() const;
  2659. +           bool                    HasParent() const;
  2660. +
  2661. +           status_t                WriteBlocks(off_t blockNumber,
  2662. +                                       const uint8* buffer,
  2663. +                                       size_t numBlocks = 1);
  2664. +
  2665. +           void                    Split();
  2666. +
  2667. +           Volume*                 GetVolume() const;
  2668. +           int32                   ID() const;
  2669. +
  2670. +           void                    AddListener(TransactionListener* listener);
  2671. +           void                    RemoveListener(
  2672. +                                       TransactionListener* listener);
  2673. +
  2674. +           void                    NotifyListeners(bool success);
  2675. +           void                    MoveListenersTo(Transaction* transaction);
  2676. +          
  2677. +           void                    SetParent(Transaction* transaction);
  2678. +           Transaction*            Parent() const;
  2679. +private:
  2680. +                                   Transaction(const Transaction& other);
  2681. +           Transaction&            operator=(const Transaction& other);
  2682. +               // no implementation
  2683. +
  2684. +           Journal*                fJournal;
  2685. +           TransactionListeners    fListeners;
  2686. +           Transaction*            fParent;
  2687. +};
  2688. +
  2689. +#endif // TRANSACTION_H
  2690. Index: src/add-ons/kernel/file_systems/ext2/BlockAllocator.cpp
  2691. ===================================================================
  2692. --- src/add-ons/kernel/file_systems/ext2/BlockAllocator.cpp (revision 0)
  2693. +++ src/add-ons/kernel/file_systems/ext2/BlockAllocator.cpp (revision 0)
  2694. @@ -0,0 +1,606 @@
  2695. +/*
  2696. + * Copyright 2001-2010, Haiku Inc. All rights reserved.
  2697. + * This file may be used under the terms of the MIT License.
  2698. + *
  2699. + * Authors:
  2700. + *     Janito V. Ferreira Filho
  2701. + */
  2702. +
  2703. +#include "BlockAllocator.h"
  2704. +
  2705. +#include <util/AutoLock.h>
  2706. +
  2707. +#include "BitmapBlock.h"
  2708. +#include "Inode.h"
  2709. +
  2710. +
  2711. +//#define TRACE_EXT2
  2712. +#ifdef TRACE_EXT2
  2713. +#  define TRACE(x...) dprintf("\33[34mext2:\33[0m " x)
  2714. +#else
  2715. +#  define TRACE(x...) ;
  2716. +#endif
  2717. +
  2718. +
  2719. +class AllocationBlockGroup : public TransactionListener {
  2720. +public:
  2721. +                       AllocationBlockGroup();
  2722. +                       ~AllocationBlockGroup();
  2723. +
  2724. +           status_t    Initialize(Volume* v, uint32 blockGroup);
  2725. +
  2726. +           status_t    ScanFreeRanges();
  2727. +           bool        IsFull() const;
  2728. +
  2729. +           status_t    Allocate(Transaction& transaction, uint32 start,
  2730. +                           uint32 length);
  2731. +           status_t    Free(Transaction& transaction, uint32 start,
  2732. +                           uint32 length);
  2733. +           status_t    FreeAll(Transaction& transaction);
  2734. +           status_t    Check(uint32 start, uint32 length);
  2735. +
  2736. +           uint32      NumBits() const;
  2737. +           uint32      FreeBits() const;
  2738. +           uint32      Start() const;
  2739. +
  2740. +           uint32      LargestStart() const;
  2741. +           uint32      LargestLength() const;
  2742. +
  2743. +           // TransactionListener implementation
  2744. +           void        TransactionDone(bool success);
  2745. +           void        RemovedFromTransaction();
  2746. +
  2747. +private:
  2748. +           void        _AddFreeRange(uint32 start, uint32 length);
  2749. +
  2750. +
  2751. +           Volume*     fVolume;
  2752. +
  2753. +           uint32      fStart;
  2754. +           uint32      fNumBits;
  2755. +           uint32      fBitmapBlock;
  2756. +
  2757. +           uint32      fFreeBits;
  2758. +           uint32      fFirstFree;
  2759. +           uint32      fLargestStart;
  2760. +           uint32      fLargestLength;
  2761. +          
  2762. +           uint32      fPreviousFreeBits;
  2763. +           uint32      fPreviousFirstFree;
  2764. +           uint32      fPreviousLargestStart;
  2765. +           uint32      fPreviousLargestLength;
  2766. +};
  2767. +
  2768. +
  2769. +class BlockAllocatorTransactionListener : public TransactionListener {
  2770. +public:
  2771. +                       BlockAllocatorTransactionListener(
  2772. +                           BlockAllocator* allocator, uint32 blocks);
  2773. +                       ~BlockAllocatorTransactionListener();
  2774. +
  2775. +           void        TransactionDone(bool success);
  2776. +           void        RemovedFromTransaction();
  2777. +private:
  2778. +           BlockAllocator* fAllocator;
  2779. +           uint32      fBlockAffected;
  2780. +};
  2781. +
  2782. +
  2783. +AllocationBlockGroup::AllocationBlockGroup()
  2784. +   :
  2785. +   fStart(0),
  2786. +   fNumBits(0),
  2787. +   fBitmapBlock(0),
  2788. +   fFreeBits(0),
  2789. +   fFirstFree(0),
  2790. +   fLargestStart(0),
  2791. +   fLargestLength(0),
  2792. +   fPreviousFreeBits(0),
  2793. +   fPreviousFirstFree(0),
  2794. +   fPreviousLargestStart(0),
  2795. +   fPreviousLargestLength(0)
  2796. +{
  2797. +}
  2798. +
  2799. +
  2800. +AllocationBlockGroup::~AllocationBlockGroup()
  2801. +{
  2802. +}
  2803. +
  2804. +
  2805. +status_t
  2806. +AllocationBlockGroup::Initialize(Volume* volume, uint32 blockGroup)
  2807. +{
  2808. +   fVolume = volume;
  2809. +
  2810. +   ext2_block_group* group;
  2811. +   status_t status = fVolume->GetBlockGroup(blockGroup, &group);
  2812. +   if (status != B_OK)
  2813. +       return status;
  2814. +
  2815. +   if (blockGroup == volume->NumGroups()) {
  2816. +       fNumBits = volume->NumBlocks() - volume->BlocksPerGroup() * blockGroup
  2817. +           - volume->FirstDataBlock();
  2818. +   } else
  2819. +       fNumBits = fVolume->BlocksPerGroup();
  2820. +
  2821. +   fBitmapBlock = group->BlockBitmap();
  2822. +
  2823. +   status = ScanFreeRanges();
  2824. +
  2825. +   fPreviousFreeBits = fFreeBits;
  2826. +   fPreviousFirstFree = fFirstFree;
  2827. +   fPreviousLargestStart = fLargestStart;
  2828. +   fPreviousLargestLength = fLargestLength;
  2829. +  
  2830. +   return status;
  2831. +}
  2832. +
  2833. +
  2834. +status_t
  2835. +AllocationBlockGroup::ScanFreeRanges()
  2836. +{
  2837. +   BitmapBlock block(fVolume, fNumBits);
  2838. +
  2839. +   if (!block.SetTo(fBitmapBlock))
  2840. +       return B_ERROR;
  2841. +
  2842. +   uint32 start = 0;
  2843. +   uint32 end = 0;
  2844. +
  2845. +   while (end < fNumBits) {
  2846. +       block.FindNextUnmarked(start);
  2847. +       end = start;
  2848. +
  2849. +       if (start != block.NumBits()) {
  2850. +           block.FindNextMarked(end);
  2851. +           _AddFreeRange(start, end);
  2852. +           start = end;
  2853. +       }
  2854. +   }
  2855. +
  2856. +   return B_OK;
  2857. +}
  2858. +
  2859. +
  2860. +bool
  2861. +AllocationBlockGroup::IsFull() const
  2862. +{
  2863. +   return fFreeBits == 0;
  2864. +}
  2865. +
  2866. +
  2867. +status_t
  2868. +AllocationBlockGroup::Allocate(Transaction& transaction, uint32 start,
  2869. +   uint32 length)
  2870. +{
  2871. +   uint32 end = start + length;
  2872. +   if (end > fLargestLength)
  2873. +       return B_BAD_DATA;
  2874. +
  2875. +   BitmapBlock block(fVolume, fNumBits);
  2876. +
  2877. +   if (!block.SetToWritable(transaction, fBitmapBlock))
  2878. +       return B_ERROR;
  2879. +  
  2880. +   if (!block.Mark(start, length)) {
  2881. +       TRACE("Failed to allocate blocks from %lu to %lu. Some were "
  2882. +           "already allocated.\n", start, start + length);
  2883. +       return B_ERROR;
  2884. +   }
  2885. +
  2886. +   transaction.AddListener(this);
  2887. +
  2888. +   fFreeBits -= length;
  2889. +
  2890. +   if (start == fLargestStart) {
  2891. +       if (fFirstFree == fLargestStart)
  2892. +           fFirstFree += length;
  2893. +
  2894. +       fLargestStart += length;
  2895. +       fLargestLength -= length;
  2896. +   } else if (start + length == fLargestStart + fLargestLength) {
  2897. +       fLargestLength -= length;
  2898. +   } else if (start < fLargestStart + fLargestLength
  2899. +           && start > fLargestStart) {
  2900. +       uint32 firstLength = start - fLargestStart;
  2901. +       uint32 secondLength = fLargestStart + fLargestLength
  2902. +           - (start + length);
  2903. +
  2904. +       if (firstLength >= secondLength) {
  2905. +           fLargestLength = firstLength;
  2906. +       } else {
  2907. +           fLargestLength = secondLength;
  2908. +           fLargestStart = start + length;
  2909. +       }
  2910. +   } else {
  2911. +       // No need to revalidate the largest free range
  2912. +       return B_OK;
  2913. +   }
  2914. +
  2915. +   if (fLargestLength < fNumBits / 2)
  2916. +       block.FindLargestUnmarkedRange(fLargestStart, fLargestLength);
  2917. +
  2918. +   return B_OK;
  2919. +}
  2920. +
  2921. +
  2922. +status_t
  2923. +AllocationBlockGroup::Free(Transaction& transaction, uint32 start,
  2924. +   uint32 length)
  2925. +{
  2926. +   uint32 end = start + length;
  2927. +
  2928. +   if (end > fLargestLength)
  2929. +       return B_BAD_DATA;
  2930. +
  2931. +   BitmapBlock block(fVolume, fNumBits);
  2932. +
  2933. +   if (!block.SetToWritable(transaction, fBitmapBlock))
  2934. +       return B_ERROR;
  2935. +
  2936. +   if (!block.Unmark(start, length)) {
  2937. +       TRACE("Failed to free blocks from %lu to %lu. Some were "
  2938. +           "already freed.\n", start, start + length);
  2939. +       return B_ERROR;
  2940. +   }
  2941. +
  2942. +   transaction.AddListener(this);
  2943. +
  2944. +   if (fFirstFree > start)
  2945. +       fFirstFree = start;
  2946. +
  2947. +   if (start + length == fLargestStart) {
  2948. +       fLargestStart = start;
  2949. +       fLargestLength += length;
  2950. +   } else if (start == fLargestStart + fLargestLength) {
  2951. +       fLargestLength += length;
  2952. +   } else if (fLargestLength >= fNumBits / 2) {
  2953. +       // May have merged with some free blocks, becoming the largest
  2954. +       uint32 newEnd = start + length;
  2955. +       block.FindNextMarked(newEnd);
  2956. +
  2957. +       uint32 newStart = start;
  2958. +       block.FindPreviousMarked(newStart);
  2959. +
  2960. +       if (newEnd - newStart > fLargestLength) {
  2961. +           fLargestLength = newEnd - newStart;
  2962. +           fLargestStart = newStart;
  2963. +       }
  2964. +   }
  2965. +
  2966. +   fFreeBits += length;
  2967. +
  2968. +   return B_OK;
  2969. +}
  2970. +
  2971. +
  2972. +status_t
  2973. +AllocationBlockGroup::FreeAll(Transaction& transaction)
  2974. +{
  2975. +   return Free(transaction, 0, fNumBits);
  2976. +}
  2977. +
  2978. +
  2979. +uint32
  2980. +AllocationBlockGroup::NumBits() const
  2981. +{
  2982. +   return fNumBits;
  2983. +}
  2984. +
  2985. +
  2986. +uint32
  2987. +AllocationBlockGroup::FreeBits() const
  2988. +{
  2989. +   return fFreeBits;
  2990. +}
  2991. +
  2992. +
  2993. +uint32
  2994. +AllocationBlockGroup::Start() const
  2995. +{
  2996. +   return fStart;
  2997. +}
  2998. +
  2999. +
  3000. +uint32
  3001. +AllocationBlockGroup::LargestStart() const
  3002. +{
  3003. +   return fLargestStart;
  3004. +}
  3005. +
  3006. +
  3007. +uint32
  3008. +AllocationBlockGroup::LargestLength() const
  3009. +{
  3010. +   return fLargestLength;
  3011. +}
  3012. +
  3013. +
  3014. +void
  3015. +AllocationBlockGroup::_AddFreeRange(uint32 start, uint32 length)
  3016. +{
  3017. +   if (IsFull()) {
  3018. +       fFirstFree = start;
  3019. +       fLargestStart = start;
  3020. +       fLargestLength = length;
  3021. +   } else if (length > fLargestLength) {
  3022. +       fLargestStart = start;
  3023. +       fLargestLength = length;
  3024. +   }
  3025. +
  3026. +   fFreeBits += length;
  3027. +}
  3028. +
  3029. +
  3030. +void
  3031. +AllocationBlockGroup::TransactionDone(bool success)
  3032. +{
  3033. +   if (success) {
  3034. +       fPreviousFreeBits = fFreeBits;
  3035. +       fPreviousFirstFree = fFirstFree;
  3036. +       fPreviousLargestStart = fLargestStart;
  3037. +       fPreviousLargestLength = fLargestLength;
  3038. +   } else {
  3039. +       fFreeBits = fPreviousFreeBits;
  3040. +       fFirstFree = fPreviousFirstFree;
  3041. +       fLargestStart = fPreviousLargestStart;
  3042. +       fLargestLength = fPreviousLargestLength;
  3043. +   }
  3044. +}
  3045. +
  3046. +
  3047. +void
  3048. +AllocationBlockGroup::RemovedFromTransaction()
  3049. +{
  3050. +   // TODO: What to do here?
  3051. +}
  3052. +
  3053. +
  3054. +BlockAllocator::BlockAllocator(Volume* volume)
  3055. +   :
  3056. +   fVolume(volume),
  3057. +   fGroups(NULL),
  3058. +   fBlocksPerGroup(volume->BlocksPerGroup()),
  3059. +   fNumBlocks(0),
  3060. +   fNumGroups(0)
  3061. +{
  3062. +   mutex_init(&fLock, "ext2 block allocator");
  3063. +}
  3064. +
  3065. +
  3066. +BlockAllocator::~BlockAllocator()
  3067. +{
  3068. +   mutex_destroy(&fLock);
  3069. +
  3070. +   if (fGroups != NULL)
  3071. +       delete [] fGroups;
  3072. +}
  3073. +
  3074. +
  3075. +status_t
  3076. +BlockAllocator::Initialize()
  3077. +{
  3078. +   fNumGroups = fVolume->NumGroups();
  3079. +   fFirstBlock = fVolume->FirstDataBlock();
  3080. +
  3081. +   fGroups = new(std::nothrow) AllocationBlockGroup[fNumGroups];
  3082. +   if (fGroups == NULL)
  3083. +       return B_NO_MEMORY;
  3084. +
  3085. +   mutex_lock(&fLock);
  3086. +       // Released by _Initialize
  3087. +
  3088. +   thread_id id = -1; // spawn_kernel_thread(
  3089. +       // (thread_func)BlockAllocator::_Initialize, "ext2 block allocator",
  3090. +       // B_LOW_PRIORITY, this);
  3091. +   if (id < B_OK)
  3092. +       return _Initialize(this);
  3093. +
  3094. +   // mutex_transfer_lock(&fLock, id);
  3095. +
  3096. +   // return resume_thread(id);
  3097. +   panic("Failed to fall back to synchronous block allocator"
  3098. +       "initialization.\n");
  3099. +   return B_ERROR;
  3100. +}
  3101. +
  3102. +
  3103. +status_t
  3104. +BlockAllocator::AllocateBlocks(Transaction& transaction, uint32 minimum,
  3105. +   uint32 maximum, uint32& blockGroup, uint32& start, uint32& length)
  3106. +{
  3107. +   MutexLocker lock(fLock);
  3108. +
  3109. +   uint32 bestStart = 0;
  3110. +   uint32 bestLength = 0;
  3111. +   uint32 bestGroup = 0;
  3112. +
  3113. +   uint32 groupNum = blockGroup;
  3114. +
  3115. +   AllocationBlockGroup* last = &fGroups[fNumGroups];
  3116. +   AllocationBlockGroup* group = &fGroups[blockGroup];
  3117. +
  3118. +   for (int32 iterations = 0; iterations < 2; iterations++) {
  3119. +       for (; group < last; ++group, ++groupNum) {
  3120. +           if (group->LargestLength() > bestLength) {
  3121. +               if (start < group->LargestStart()) {
  3122. +                   bestStart = group->LargestStart();
  3123. +                   bestLength = group->LargestLength();
  3124. +                   bestGroup = groupNum;
  3125. +
  3126. +                   if (bestLength >= maximum)
  3127. +                       break;
  3128. +               }
  3129. +           }
  3130. +
  3131. +           start = 0;
  3132. +       }
  3133. +
  3134. +       if (bestLength >= maximum)
  3135. +           break;
  3136. +
  3137. +       groupNum = 0;
  3138. +
  3139. +       group = &fGroups[0];
  3140. +       last = &fGroups[blockGroup];
  3141. +   }
  3142. +
  3143. +   if (bestLength < minimum)
  3144. +       return B_DEVICE_FULL;
  3145. +
  3146. +   if (bestLength > maximum)
  3147. +       bestLength = maximum;
  3148. +
  3149. +   status_t status = fGroups[bestGroup].Allocate(transaction, bestStart,
  3150. +       bestLength);
  3151. +   if (status != B_OK) {
  3152. +       TRACE("Failed to allocate %lu blocks inside block group %lu.\n",
  3153. +           bestLength, bestGroup);
  3154. +       return status;
  3155. +   }
  3156. +
  3157. +   start = bestStart;
  3158. +   length = bestLength;
  3159. +   blockGroup = bestGroup;
  3160. +
  3161. +   return B_OK;
  3162. +}
  3163. +
  3164. +
  3165. +status_t
  3166. +BlockAllocator::Allocate(Transaction& transaction, Inode* inode,
  3167. +   off_t numBlocks, uint32 minimum, uint32& start, uint32& allocated)
  3168. +{
  3169. +   if (numBlocks <= 0)
  3170. +       return B_ERROR;
  3171. +
  3172. +   uint32 group = inode->ID() / fVolume->InodesPerGroup();
  3173. +   uint32 preferred = 0;
  3174. +
  3175. +   if (inode->Size() > 0) {
  3176. +       // Try to allocate near it's last blocks
  3177. +       ext2_data_stream* dataStream = &inode->Node().stream;
  3178. +       uint32 numBlocks = inode->Size() / fVolume->BlockSize() + 1;
  3179. +       uint32 lastBlock = 0;
  3180. +
  3181. +       // DANGER! What happens with sparse files?
  3182. +       if (numBlocks < EXT2_DIRECT_BLOCKS) {
  3183. +           // Only direct blocks
  3184. +           lastBlock = dataStream->direct[numBlocks];
  3185. +       } else {
  3186. +           numBlocks -= EXT2_DIRECT_BLOCKS - 1;
  3187. +           uint32 numIndexes = fVolume->BlockSize() / 4;
  3188. +               // block size / sizeof(int32)
  3189. +           uint32 numIndexes2 = numIndexes * numIndexes;
  3190. +           uint32 numIndexes3 = numIndexes2 * numIndexes;
  3191. +           uint32 indexesInIndirect = numIndexes;
  3192. +           uint32 indexesInDoubleIndirect = indexesInIndirect
  3193. +               + numIndexes2;
  3194. +           // uint32 indexesInTripleIndirect = indexesInDoubleIndirect
  3195. +               // + numIndexes3;
  3196. +
  3197. +           uint32 doubleIndirectBlock = EXT2_DIRECT_BLOCKS + 1;
  3198. +           uint32 indirectBlock = EXT2_DIRECT_BLOCKS;
  3199. +
  3200. +           CachedBlock cached(fVolume);
  3201. +           uint32* indirectData;
  3202. +
  3203. +           if (numBlocks > indexesInDoubleIndirect) {
  3204. +               // Triple indirect blocks
  3205. +               indirectData = (uint32*)cached.SetTo(EXT2_DIRECT_BLOCKS + 2);
  3206. +               if (indirectData == NULL)
  3207. +                   return B_IO_ERROR;
  3208. +
  3209. +               uint32 index = (numBlocks - indexesInDoubleIndirect)
  3210. +                   / numIndexes3;
  3211. +               doubleIndirectBlock = indirectData[index];
  3212. +           }
  3213. +
  3214. +           if (numBlocks > indexesInIndirect) {
  3215. +               // Double indirect blocks
  3216. +               indirectData = (uint32*)cached.SetTo(doubleIndirectBlock);
  3217. +               if (indirectData == NULL)
  3218. +                   return B_IO_ERROR;
  3219. +
  3220. +               uint32 index = (numBlocks - indexesInIndirect) / numIndexes2;
  3221. +               indirectBlock = indirectData[index];
  3222. +           }
  3223. +
  3224. +           indirectData = (uint32*)cached.SetTo(indirectBlock);
  3225. +               if (indirectData == NULL)
  3226. +                   return B_IO_ERROR;
  3227. +
  3228. +           uint32 index = numBlocks / numIndexes;
  3229. +           lastBlock = indirectData[index];
  3230. +       }
  3231. +
  3232. +       group = (lastBlock - fFirstBlock) / fBlocksPerGroup;
  3233. +       preferred = (lastBlock - fFirstBlock) % fBlocksPerGroup + 1;
  3234. +   }
  3235. +
  3236. +   // TODO: Apply some more policies
  3237. +
  3238. +   return AllocateBlocks(transaction, minimum, minimum + 8, group, start,
  3239. +       allocated);
  3240. +}
  3241. +
  3242. +
  3243. +status_t
  3244. +BlockAllocator::Free(Transaction& transaction, uint32 start, uint32 length)
  3245. +{
  3246. +   MutexLocker lock(fLock);
  3247. +
  3248. +   uint32 group = (start - fFirstBlock) / fBlocksPerGroup;
  3249. +   start = (start - fFirstBlock) % fBlocksPerGroup;
  3250. +   uint32 lastGroup = (start + length - fFirstBlock) / fBlocksPerGroup;
  3251. +
  3252. +   if (group == lastGroup)
  3253. +       return fGroups[group].Free(transaction, start, length);
  3254. +
  3255. +   status_t status = fGroups[group].Free(transaction, start,
  3256. +       fGroups[group].NumBits());
  3257. +   if (status != B_OK)
  3258. +       return status;
  3259. +
  3260. +   for (++group; group < lastGroup; ++group) {
  3261. +       status = fGroups[group].FreeAll(transaction);
  3262. +       if (status != B_OK)
  3263. +           return status;
  3264. +   }
  3265. +
  3266. +   return fGroups[group].Free(transaction, 0, (start + length - fFirstBlock)
  3267. +       % fBlocksPerGroup);
  3268. +}
  3269. +
  3270. +
  3271. +/*static*/ status_t
  3272. +BlockAllocator::_Initialize(BlockAllocator* allocator)
  3273. +{
  3274. +   // fLock is already heald
  3275. +   Volume* volume = allocator->fVolume;
  3276. +
  3277. +   AllocationBlockGroup* groups = allocator->fGroups;
  3278. +   uint32 numGroups = allocator->fNumGroups;
  3279. +
  3280. +   uint32 freeBlocks = 0;
  3281. +
  3282. +   for (uint32 i = 0; i < numGroups; ++i) {
  3283. +       status_t status = groups[i].Initialize(volume, i);
  3284. +       if (status != B_OK) {
  3285. +           mutex_unlock(&allocator->fLock);
  3286. +           return status;
  3287. +       }
  3288. +
  3289. +       freeBlocks += groups[i].FreeBits();
  3290. +   }
  3291. +
  3292. +   mutex_unlock(&allocator->fLock);
  3293. +
  3294. +   if (freeBlocks != volume->FreeBlocks()) {
  3295. +       TRACE("Counted free blocks doesn't match value in the superblock.\n");
  3296. +       return B_BAD_DATA;
  3297. +   }
  3298. +
  3299. +   return B_OK;
  3300. +}
  3301.  
  3302. Property changes on: src/add-ons/kernel/file_systems/ext2/BlockAllocator.cpp
  3303. ___________________________________________________________________
  3304. Added: svn:executable
  3305.    + *
  3306.  
  3307. Index: src/add-ons/kernel/file_systems/ext2/Inode.cpp
  3308. ===================================================================
  3309. --- src/add-ons/kernel/file_systems/ext2/Inode.cpp  (revision 37473)
  3310. +++ src/add-ons/kernel/file_systems/ext2/Inode.cpp  (working copy)
  3311. @@ -8,6 +8,7 @@
  3312.  
  3313.  #include <fs_cache.h>
  3314.  #include <string.h>
  3315. +#include <util/AutoLock.h>
  3316.  
  3317.  #include "CachedBlock.h"
  3318.  
  3319. @@ -32,50 +33,95 @@
  3320.     rw_lock_init(&fLock, "ext2 inode");
  3321.  
  3322.     uint32 block;
  3323. -   if (volume->GetInodeBlock(id, block) == B_OK) {
  3324. +   fInitStatus = volume->GetInodeBlock(id, block);
  3325. +   if (fInitStatus == B_OK) {
  3326.         TRACE("inode %Ld at block %lu\n", ID(), block);
  3327. -       uint8* inodeBlock = (uint8*)block_cache_get(volume->BlockCache(),
  3328. -           block);
  3329. +
  3330. +       CachedBlock cached(volume);
  3331. +       uint8* inodeBlock = (uint8*)cached.SetTo(block);
  3332. +
  3333.         if (inodeBlock != NULL) {
  3334. -           fNode = (ext2_inode*)(inodeBlock + volume->InodeBlockIndex(id)
  3335. -               * volume->InodeSize());
  3336. -       }
  3337. +           ext2_inode* inode = (ext2_inode*)(inodeBlock
  3338. +               + volume->InodeBlockIndex(id) * volume->InodeSize());
  3339. +          
  3340. +           fNode = (ext2_inode*)(new(std::nothrow) uint8[volume->InodeSize()]);
  3341. +           if (fNode == NULL)
  3342. +               fInitStatus = B_NO_MEMORY;
  3343. +           else
  3344. +               memcpy(fNode, inode, volume->InodeSize());
  3345. +       } else
  3346. +           fInitStatus = B_IO_ERROR;
  3347.     }
  3348.  
  3349. -   if (fNode != NULL) {
  3350. -       // TODO: we don't need a cache for short symlinks
  3351. +   if (fInitStatus == B_OK) {
  3352.         fCache = file_cache_create(fVolume->ID(), ID(), Size());
  3353.         fMap = file_map_create(fVolume->ID(), ID(), Size());
  3354. -   }
  3355. +       fCached = true;
  3356. +
  3357. +       if (fCache == NULL || Size() == 0 || IsDirectory() || (IsSymLink()
  3358. +               && Size() < 60)) {
  3359. +           fInitStatus = DisableFileCache();
  3360. +       } else
  3361. +           fInitStatus = B_OK;
  3362. +   } else
  3363. +       fCached = false;
  3364.  }
  3365.  
  3366.  
  3367.  Inode::~Inode()
  3368.  {
  3369. -   file_cache_delete(FileCache());
  3370. -   file_map_delete(Map());
  3371. +   if (fCached) {
  3372. +       file_cache_delete(FileCache());
  3373. +       file_map_delete(Map());
  3374. +   }
  3375.  
  3376.     if (fAttributesBlock) {
  3377.         uint32 block = B_LENDIAN_TO_HOST_INT32(Node().file_access_control);
  3378.         block_cache_put(fVolume->BlockCache(), block);
  3379.     }
  3380.  
  3381. -   if (fNode != NULL) {
  3382. +   delete fNode;
  3383. +
  3384. +   /*if (fNode != NULL) {
  3385.         uint32 block;
  3386.         if (fVolume->GetInodeBlock(ID(), block) == B_OK)
  3387.             block_cache_put(fVolume->BlockCache(), block);
  3388. -   }
  3389. +   }*/
  3390.  }
  3391.  
  3392.  
  3393.  status_t
  3394.  Inode::InitCheck()
  3395.  {
  3396. -   return fNode != NULL ? B_OK : B_ERROR;
  3397. +   return fInitStatus;
  3398.  }
  3399.  
  3400.  
  3401.  status_t
  3402. +Inode::WriteBack(Transaction& transaction)
  3403. +{
  3404. +   WriteLocker lock(fLock);
  3405. +
  3406. +   uint32 inodeBlock;
  3407. +
  3408. +   status_t status = fVolume->GetInodeBlock(fID, inodeBlock);
  3409. +   if (status != B_OK)
  3410. +       return status;
  3411. +
  3412. +   CachedBlock cached(fVolume);
  3413. +   uint8* inodeBlockData = cached.SetToWritable(transaction, inodeBlock);
  3414. +   if (inodeBlockData == NULL)
  3415. +       return B_IO_ERROR;
  3416. +
  3417. +   memcpy(inodeBlockData +
  3418. +           fVolume->InodeBlockIndex(fID) * fVolume->InodeSize(),
  3419. +       (uint8*)fNode, sizeof(ext2_inode));
  3420. +
  3421. +   return B_OK;
  3422. +}
  3423. +
  3424. +
  3425. +status_t
  3426.  Inode::CheckPermissions(int accessMode) const
  3427.  {
  3428.     uid_t user = geteuid();
  3429. @@ -114,8 +160,10 @@
  3430.     uint32 perIndirectBlock = perBlock * perBlock;
  3431.     uint32 index = offset >> fVolume->BlockShift();
  3432.  
  3433. -   if (offset >= Size())
  3434. +   if (offset >= Size()) {
  3435. +       TRACE("FindBlock: offset larger than inode size\n");
  3436.         return B_ENTRY_NOT_FOUND;
  3437. +   }
  3438.  
  3439.     // TODO: we could return the size of the sparse range, as this might be more
  3440.     // than just a block
  3441. @@ -203,7 +251,8 @@
  3442.  
  3443.     // set/check boundaries for pos/length
  3444.     if (pos < 0) {
  3445. -       TRACE("inode %Ld: ReadAt failed(pos %Ld, length %lu)\n", ID(), pos, length);
  3446. +       TRACE("inode %Ld: ReadAt failed(pos %Ld, length %lu)\n", ID(), pos,
  3447. +           length);
  3448.         return B_BAD_VALUE;
  3449.     }
  3450.  
  3451. @@ -245,3 +294,34 @@
  3452.     *_length = length;
  3453.     return B_NO_ERROR;
  3454.  }
  3455. +
  3456. +
  3457. +/*static*/ status_t
  3458. +Inode::Create(Transaction& transaction, Inode* parent, const char* name,
  3459. +   int32 mode, int openMode, uint32 type, bool* _created, ino_t* _id,
  3460. +   Inode** _inode, fs_vnode_ops* vnodeOps, uint32 publishFlags)
  3461. +{
  3462. +   //DirectoryIterator* entries = NULL;
  3463. +
  3464. +   if (parent != NULL) {
  3465. +   }
  3466. +
  3467. +   return B_OK;
  3468. +}
  3469. +
  3470. +
  3471. +status_t
  3472. +Inode::DisableFileCache()
  3473. +{
  3474. +   if (fCache == NULL) {
  3475. +       fCached = false;
  3476. +       return B_OK;
  3477. +   }
  3478. +
  3479. +   status_t status = file_cache_disable(fCache);
  3480. +
  3481. +   if (status == B_OK)
  3482. +       fCached = false;
  3483. +
  3484. +   return B_OK;
  3485. +}
  3486. Index: src/add-ons/kernel/file_systems/ext2/HashRevokeManager.h
  3487. ===================================================================
  3488. --- src/add-ons/kernel/file_systems/ext2/HashRevokeManager.h    (revision 0)
  3489. +++ src/add-ons/kernel/file_systems/ext2/HashRevokeManager.h    (revision 0)
  3490. @@ -0,0 +1,47 @@
  3491. +/*
  3492. + * Copyright 2001-2010, Haiku Inc. All rights reserved.
  3493. + * This file may be used under the terms of the MIT License.
  3494. + *
  3495. + * Authors:
  3496. + *     Janito V. Ferreira Filho
  3497. + */
  3498. +#ifndef HASHREVOKEMANAGER_H
  3499. +#define HASHREVOKEMANAGER_H
  3500. +
  3501. +#include <util/khash.h>
  3502. +
  3503. +#include "RevokeManager.h"
  3504. +
  3505. +
  3506. +struct RevokeElement {
  3507. +   RevokeElement*  next;   // Next in hash
  3508. +   uint32          block;
  3509. +   uint32          commitID;
  3510. +};
  3511. +
  3512. +
  3513. +class HashRevokeManager : public RevokeManager {
  3514. +public:
  3515. +                       HashRevokeManager();
  3516. +   virtual             ~HashRevokeManager();
  3517. +
  3518. +           status_t    Init();
  3519. +
  3520. +   virtual status_t    Insert(uint32 block, uint32 commitID);
  3521. +   virtual status_t    Remove(uint32 block);
  3522. +   virtual bool        Lookup(uint32 block, uint32 commitID);
  3523. +          
  3524. +   static  int         Compare(void* element, const void* key);
  3525. +   static  uint32      Hash(void* element, const void* key, uint32 range);
  3526. +
  3527. +protected:
  3528. +           status_t    _ForceInsert(uint32 block, uint32 commitID);
  3529. +
  3530. +private:
  3531. +           hash_table* fHash;
  3532. +
  3533. +   const   int         kInitialHashSize;
  3534. +};
  3535. +
  3536. +#endif // HASHREVOKEMANAGER_H
  3537. +
  3538.  
  3539. Property changes on: src/add-ons/kernel/file_systems/ext2/HashRevokeManager.h
  3540. ___________________________________________________________________
  3541. Added: svn:executable
  3542.    + *
  3543.  
  3544. Index: src/add-ons/kernel/file_systems/ext2/kernel_interface.cpp
  3545. ===================================================================
  3546. --- src/add-ons/kernel/file_systems/ext2/kernel_interface.cpp   (revision 37473)
  3547. +++ src/add-ons/kernel/file_systems/ext2/kernel_interface.cpp   (working copy)
  3548. @@ -13,6 +13,7 @@
  3549.  #include <fs_info.h>
  3550.  
  3551.  #include "AttributeIterator.h"
  3552. +#include "CachedBlock.h"
  3553.  #include "DirectoryIterator.h"
  3554.  #include "ext2.h"
  3555.  #include "HTree.h"
  3556. @@ -339,12 +340,52 @@
  3557.         if (!strcmp(buffer, name))
  3558.             break;
  3559.     }
  3560. -
  3561. +  
  3562.     return get_vnode(volume->FSVolume(), *_vnodeID, NULL);
  3563.  }
  3564.  
  3565.  
  3566.  static status_t
  3567. +ext2_ioctl(fs_volume* _volume, fs_vnode* _node, void* _cookie, uint32 cmd,
  3568. +   void* buffer, size_t bufferLength)
  3569. +{
  3570. +   Volume* volume = (Volume*)_volume->private_volume;
  3571. +   switch (cmd) {
  3572. +       case 56742:
  3573. +       {
  3574. +           // Test the block allocator
  3575. +           Transaction transaction(volume->GetJournal());
  3576. +           CachedBlock cached(volume);
  3577. +           uint32 blocksPerGroup = volume->BlocksPerGroup();
  3578. +           uint32 blockSize  = volume->BlockSize();
  3579. +           uint32 firstBlock = volume->FirstDataBlock();
  3580. +           uint32 start = 0;
  3581. +           uint32 group = 0;
  3582. +           uint32 length;
  3583. +
  3584. +           TRACE("Attempting to test the ext3 block allocator.\n");
  3585. +
  3586. +           while (volume->AllocateBlocks(transaction, 1, 64, group, start,
  3587. +                   length) == B_OK) {
  3588. +               TRACE("Allocated blocks %lu-%lu\n", start, length);
  3589. +               uint32 blockNum = start + group * blocksPerGroup - firstBlock;
  3590. +
  3591. +               for (uint32 i = 0; i < length; ++i) {
  3592. +                   uint8* block = cached.SetToWritable(transaction, blockNum);
  3593. +                   memset(block, 0, blockSize);
  3594. +                   blockNum++;
  3595. +               }
  3596. +           }
  3597. +
  3598. +           return B_OK;
  3599. +       }
  3600. +   }
  3601. +
  3602. +   return B_OK;
  3603. +}
  3604. +
  3605. +
  3606. +static status_t
  3607.  ext2_read_stat(fs_volume* _volume, fs_vnode* _node, struct stat* stat)
  3608.  {
  3609.     Inode* inode = (Inode*)_node->private_node;
  3610. @@ -748,8 +789,8 @@
  3611.  
  3612.     &ext2_get_file_map,
  3613.  
  3614. +   &ext2_ioctl,
  3615.     NULL,
  3616. -   NULL,
  3617.     NULL,   // fs_select
  3618.     NULL,   // fs_deselect
  3619.     NULL,
  3620. Index: src/add-ons/kernel/file_systems/ext2/InodeAllocator.h
  3621. ===================================================================
  3622. --- src/add-ons/kernel/file_systems/ext2/InodeAllocator.h   (revision 0)
  3623. +++ src/add-ons/kernel/file_systems/ext2/InodeAllocator.h   (revision 0)
  3624. @@ -0,0 +1,37 @@
  3625. +/*
  3626. + * Copyright 2001-2010, Haiku Inc. All rights reserved.
  3627. + * This file may be used under the terms of the MIT License.
  3628. + *
  3629. + * Authors:
  3630. + *     Janito V. Ferreira Filho
  3631. + */
  3632. +#ifndef INODEALLOCATOR_H
  3633. +#define INODEALLOCATOR_H
  3634. +
  3635. +#include <lock.h>
  3636. +
  3637. +#include "Transaction.h"
  3638. +
  3639. +
  3640. +class Volume;
  3641. +
  3642. +
  3643. +class InodeAllocator {
  3644. +public:
  3645. +                       InodeAllocator(Volume* volume);
  3646. +                       ~InodeAllocator();
  3647. +
  3648. +           status_t    New(Transaction& transaction,
  3649. +                           uint32 prefferedBlockGroup, ino_t& id);
  3650. +
  3651. +private:
  3652. +           status_t    _MarkInBitmap(Transaction& transaction,
  3653. +                           uint32 bitmapBlock, uint32 blockGroup,
  3654. +                           uint32 numInodes, ino_t& id);
  3655. +
  3656. +
  3657. +           Volume*     fVolume;
  3658. +           mutex       fLock;
  3659. +};
  3660. +
  3661. +#endif // INODEALLOCATOR_H
  3662.  
  3663. Property changes on: src/add-ons/kernel/file_systems/ext2/InodeAllocator.h
  3664. ___________________________________________________________________
  3665. Added: svn:executable
  3666.    + *
  3667.  
  3668. Index: src/add-ons/kernel/file_systems/ext2/HTree.cpp
  3669. ===================================================================
  3670. --- src/add-ons/kernel/file_systems/ext2/HTree.cpp  (revision 37473)
  3671. +++ src/add-ons/kernel/file_systems/ext2/HTree.cpp  (working copy)
  3672. @@ -7,6 +7,7 @@
  3673.   */
  3674.  
  3675.  
  3676. +#include "CachedBlock.h"
  3677.  #include "HTree.h"
  3678.  
  3679.  #include <new>
  3680. @@ -75,6 +76,7 @@
  3681.  
  3682.  HTree::~HTree()
  3683.  {
  3684. +   delete fRootEntry;
  3685.  }
  3686.  
  3687.  
  3688. @@ -92,14 +94,22 @@
  3689.         return B_OK;
  3690.     }
  3691.    
  3692. -   HTreeRoot root;
  3693. -   size_t length = sizeof(root);
  3694. +   uint32 blockNum;
  3695. +   status_t status = fDirectory->FindBlock(0, blockNum);
  3696. +   if (status != B_OK) {
  3697. +       *iterator = new(std::nothrow) DirectoryIterator(fDirectory);
  3698. +      
  3699. +       if (*iterator == NULL)
  3700. +           return B_NO_MEMORY;
  3701. +       return B_OK;
  3702. +   }
  3703. +
  3704. +   CachedBlock cached(fDirectory->GetVolume());
  3705. +   const uint8* block = cached.SetTo(blockNum);
  3706. +
  3707. +   HTreeRoot* root = (HTreeRoot*)block;
  3708.    
  3709. -   status_t status = fDirectory->ReadAt(0, (uint8*)&root, &length);
  3710. -   if (status < B_OK)
  3711. -       return status;
  3712. -  
  3713. -   if (length != sizeof(root) || !root.IsValid()) {
  3714. +   if (!root->IsValid()) {
  3715.         // Fallback to linear search
  3716.         *iterator = new(std::nothrow) DirectoryIterator(fDirectory);
  3717.         if (*iterator == NULL)
  3718. @@ -108,21 +118,22 @@
  3719.         return B_OK;
  3720.     }
  3721.    
  3722. -   uint32 hash = _Hash(name, root.hash_version);
  3723. +   uint32 hash = _Hash(name, root->hash_version);
  3724.    
  3725. -   off_t start = (off_t)root.root_info_length
  3726. +   off_t start = (off_t)root->root_info_length
  3727.         + 2 * (sizeof(HTreeFakeDirEntry) + 4);
  3728.  
  3729. +   delete fRootEntry;
  3730. +
  3731.     fRootEntry = new(std::nothrow) HTreeEntryIterator(start, fDirectory);
  3732.     if (fRootEntry == NULL)
  3733.         return B_NO_MEMORY;
  3734.    
  3735. -   fRootDeleter.SetTo(fRootEntry);
  3736.     status = fRootEntry->Init();
  3737.     if (status != B_OK)
  3738.         return status;
  3739.    
  3740. -   return fRootEntry->Lookup(hash, (uint32)root.indirection_levels, iterator);
  3741. +   return fRootEntry->Lookup(hash, (uint32)root->indirection_levels, iterator);
  3742.  }
  3743.  
  3744.  
  3745. @@ -146,7 +157,7 @@
  3746.             hash = 0;
  3747.     };
  3748.  
  3749. -   TRACE("Filename hash: %u\n", hash);
  3750. +   TRACE("Filename hash: %lu\n", hash);
  3751.    
  3752.     return hash & ~1;
  3753.  }
  3754. @@ -354,7 +365,7 @@
  3755.     int completeIterations = length / 4;
  3756.    
  3757.     for (int i = 0; i < completeIterations; ++i) {
  3758. -       uint32 value = 0 | *(string++);
  3759. +       uint32 value = (padding << 8) | *(string++);
  3760.         value = (value << 8) | *(string++);
  3761.         value = (value << 8) | *(string++);
  3762.         value = (value << 8) | *(string++);
  3763.  
  3764. Property changes on: src/add-ons/kernel/file_systems/ext2/HTree.cpp
  3765. ___________________________________________________________________
  3766. Added: svn:executable
  3767.    + *
  3768.  
  3769. Index: src/add-ons/kernel/file_systems/ext2/NoJournal.cpp
  3770. ===================================================================
  3771. --- src/add-ons/kernel/file_systems/ext2/NoJournal.cpp  (revision 0)
  3772. +++ src/add-ons/kernel/file_systems/ext2/NoJournal.cpp  (revision 0)
  3773. @@ -0,0 +1,75 @@
  3774. +/*
  3775. + * Copyright 2001-2010, Haiku Inc. All rights reserved.
  3776. + * This file may be used under the terms of the MIT License.
  3777. + *
  3778. + * Authors:
  3779. + *     Janito V. Ferreira Filho
  3780. + */
  3781. +
  3782. +#include "NoJournal.h"
  3783. +
  3784. +#include <fs_cache.h>
  3785. +
  3786. +
  3787. +//#define TRACE_EXT2
  3788. +#ifdef TRACE_EXT2
  3789. +#  define TRACE(x...) dprintf("\33[34mext2:\33[0m " x)
  3790. +#else
  3791. +#  define TRACE(x...) ;
  3792. +#endif
  3793. +
  3794. +
  3795. +NoJournal::NoJournal(Volume* volume)
  3796. +   :
  3797. +   Journal()
  3798. +{
  3799. +   fFilesystemVolume = volume;
  3800. +   fFilesystemBlockCache = volume->BlockCache();
  3801. +   fHasSubTransaction = false;
  3802. +   fSeparateSubTransactions = false;
  3803. +}
  3804. +
  3805. +
  3806. +NoJournal::~NoJournal()
  3807. +{
  3808. +}
  3809. +
  3810. +
  3811. +status_t
  3812. +NoJournal::InitCheck()
  3813. +{
  3814. +   return B_OK;
  3815. +}
  3816. +
  3817. +
  3818. +status_t
  3819. +NoJournal::Recover()
  3820. +{
  3821. +   return B_OK;
  3822. +}
  3823. +
  3824. +
  3825. +status_t
  3826. +NoJournal::StartLog()
  3827. +{
  3828. +   return B_OK;
  3829. +}
  3830. +
  3831. +
  3832. +status_t
  3833. +NoJournal::_WriteTransactionToLog()
  3834. +{
  3835. +   TRACE("Ending transaction %ld\n", fTransactionID);
  3836. +
  3837. +   fTransactionID = cache_end_transaction(fFilesystemBlockCache,
  3838. +       fTransactionID, _TransactionWritten, NULL);
  3839. +  
  3840. +   return B_OK;
  3841. +}
  3842. +
  3843. +
  3844. +/*static*/ void
  3845. +NoJournal::_TransactionWritten(int32 transactionID, int32 event, void* param)
  3846. +{
  3847. +   TRACE("Transaction %ld checkpointed\n", transactionID);
  3848. +}
  3849. Index: src/add-ons/kernel/file_systems/ext2/HTreeEntryIterator.h
  3850. ===================================================================
  3851. --- src/add-ons/kernel/file_systems/ext2/HTreeEntryIterator.h   (revision 37473)
  3852. +++ src/add-ons/kernel/file_systems/ext2/HTreeEntryIterator.h   (working copy)
  3853. @@ -26,7 +26,7 @@
  3854.                                     DirectoryIterator** iterator);
  3855.             bool                HasCollision() { return fHasCollision; }
  3856.                        
  3857. -           status_t            GetNext(off_t& offset);
  3858. +           status_t            GetNext(uint32& offset);
  3859.  private:
  3860.                                 HTreeEntryIterator(uint32 block,
  3861.                                     uint32 blockSize, Inode* directory,
  3862. @@ -34,17 +34,20 @@
  3863.                                     bool hasCollision);
  3864.  
  3865.  private:
  3866. +           Inode*              fDirectory;
  3867. +           Volume*             fVolume;
  3868. +           status_t            fInitStatus;
  3869. +
  3870.             bool                fHasCollision;
  3871.             uint16              fLimit, fCount;
  3872. +           uint16              fCurrentEntry;
  3873.  
  3874.             uint32              fBlockSize;
  3875. -           Inode*              fDirectory;
  3876. -           off_t               fOffset;
  3877. -           off_t               fMaxOffset;
  3878. +           uint32              fBlockNum;
  3879. +           uint32              fDisplacement;
  3880.  
  3881.             HTreeEntryIterator* fParent;
  3882.             HTreeEntryIterator* fChild;
  3883. -           ObjectDeleter<HTreeEntryIterator> fChildDeleter;
  3884.  };
  3885.  
  3886.  #endif // HTREE_ENTRY_ITERATOR_H
  3887. Index: src/add-ons/kernel/file_systems/ext2/Volume.h
  3888. ===================================================================
  3889. --- src/add-ons/kernel/file_systems/ext2/Volume.h   (revision 37473)
  3890. +++ src/add-ons/kernel/file_systems/ext2/Volume.h   (working copy)
  3891. @@ -9,8 +9,12 @@
  3892.  #include <lock.h>
  3893.  
  3894.  #include "ext2.h"
  3895. +#include "BlockAllocator.h"
  3896. +#include "InodeAllocator.h"
  3897. +#include "Transaction.h"
  3898.  
  3899.  class Inode;
  3900. +class Journal;
  3901.  
  3902.  
  3903.  enum volume_flags {
  3904. @@ -18,7 +22,7 @@
  3905.  };
  3906.  
  3907.  
  3908. -class Volume {
  3909. +class Volume : public TransactionListener {
  3910.  public:
  3911.                                 Volume(fs_volume* volume);
  3912.                                 ~Volume();
  3913. @@ -40,30 +44,58 @@
  3914.  
  3915.             uint32              NumInodes() const
  3916.                                     { return fNumInodes; }
  3917. +           uint32              NumGroups() const
  3918. +                                   { return fNumGroups; }
  3919.             off_t               NumBlocks() const
  3920.                                     { return fSuperBlock.NumBlocks(); }
  3921.             off_t               FreeBlocks() const
  3922.                                     { return fSuperBlock.FreeBlocks(); }
  3923. +           uint32              FirstDataBlock() const
  3924. +                                   { return fFirstDataBlock; }
  3925.  
  3926.             uint32              BlockSize() const { return fBlockSize; }
  3927.             uint32              BlockShift() const { return fBlockShift; }
  3928. +           uint32              BlocksPerGroup() const
  3929. +                                   { return fSuperBlock.BlocksPerGroup(); }
  3930.             uint32              InodeSize() const
  3931.                                     { return fSuperBlock.InodeSize(); }
  3932. +           uint32              InodesPerGroup() const
  3933. +                                   { return fSuperBlock.InodesPerGroup(); }
  3934.             ext2_super_block&   SuperBlock() { return fSuperBlock; }
  3935.  
  3936.             status_t            GetInodeBlock(ino_t id, uint32& block);
  3937.             uint32              InodeBlockIndex(ino_t id) const;
  3938.             status_t            GetBlockGroup(int32 index,
  3939.                                     ext2_block_group** _group);
  3940. -          
  3941. +
  3942. +           Journal*            GetJournal() { return fJournal; }
  3943. +
  3944.             bool                IndexedDirectories() const
  3945.                                     { return (fSuperBlock.CompatibleFeatures()
  3946.                                         & EXT2_FEATURE_DIRECTORY_INDEX) != 0; }
  3947.  
  3948. +           status_t            AllocateInode(Transaction& transaction,
  3949. +                                   uint32 preferredBlockGroup, ino_t& id);
  3950. +
  3951. +           status_t            AllocateBlocks(Transaction& transaction,
  3952. +                                   uint32 blockGroup, uint32 minimum,
  3953. +                                   uint32 maximum, uint32& start,
  3954. +                                   uint32& length);
  3955. +
  3956. +           status_t            LoadSuperBlock();
  3957. +           status_t            WriteSuperBlock(Transaction& transaction);
  3958. +
  3959.             // cache access
  3960.             void*               BlockCache() { return fBlockCache; }
  3961.  
  3962. +           status_t            FlushDevice();
  3963. +           status_t            Sync();
  3964. +  
  3965.     static  status_t            Identify(int fd, ext2_super_block* superBlock);
  3966. +          
  3967. +           // TransactionListener functions
  3968. +           void                TransactionDone(bool success);
  3969. +           void                RemovedFromTransaction();
  3970.  
  3971.  private:
  3972.     static  uint32              _UnsupportedIncompatibleFeatures(
  3973. @@ -76,12 +108,21 @@
  3974.             int                 fDevice;
  3975.             ext2_super_block    fSuperBlock;
  3976.             char                fName[32];
  3977. +
  3978. +           BlockAllocator      fBlockAllocator;
  3979. +           InodeAllocator      fInodeAllocator;
  3980. +           Journal*            fJournal;
  3981. +           Inode*              fJournalInode;
  3982. +
  3983.             uint32              fFlags;
  3984.             uint32              fBlockSize;
  3985.             uint32              fBlockShift;
  3986.             uint32              fFirstDataBlock;
  3987. +
  3988.             uint32              fNumInodes;
  3989.             uint32              fNumGroups;
  3990. +           uint32              fFreeBlocks;
  3991. +           uint32              fFreeInodes;
  3992.             uint32              fGroupsPerBlock;
  3993.             ext2_block_group**  fGroupBlocks;
  3994.             uint32              fInodesPerBlock;
  3995. Index: src/add-ons/kernel/file_systems/ext2/DirectoryIterator.cpp
  3996. ===================================================================
  3997. --- src/add-ons/kernel/file_systems/ext2/DirectoryIterator.cpp  (revision 37473)
  3998. +++ src/add-ons/kernel/file_systems/ext2/DirectoryIterator.cpp  (working copy)
  3999. @@ -8,6 +8,7 @@
  4000.  
  4001.  #include <string.h>
  4002.  
  4003. +#include "CachedBlock.h"
  4004.  #include "HTree.h"
  4005.  #include "Inode.h"
  4006.  
  4007. @@ -23,7 +24,9 @@
  4008.  DirectoryIterator::DirectoryIterator(Inode* inode)
  4009.     :
  4010.     fInode(inode),
  4011. -   fOffset(0)
  4012. +   fBlock(0),
  4013. +   fDisplacement(0),
  4014. +   fBlockSize(inode->GetVolume()->BlockSize())
  4015.  {
  4016.  }
  4017.  
  4018. @@ -34,60 +37,129 @@
  4019.  
  4020.  
  4021.  status_t
  4022. +DirectoryIterator::InitCheck()
  4023. +{
  4024. +   return B_OK;
  4025. +}
  4026. +
  4027. +
  4028. +status_t
  4029.  DirectoryIterator::GetNext(char* name, size_t* _nameLength, ino_t* _id)
  4030.  {
  4031. -   if (fOffset + sizeof(ext2_dir_entry) >= fInode->Size()) {
  4032. +   if (fDisplacement + sizeof(ext2_dir_entry) >= fInode->Size()) {
  4033.         TRACE("DirectoryIterator::GetNext() out of entries\n");
  4034.         return B_ENTRY_NOT_FOUND;
  4035.     }
  4036.  
  4037. -   ext2_dir_entry entry;
  4038. +   CachedBlock cached(fInode->GetVolume());
  4039. +   ext2_dir_entry* entry;
  4040. +   uint32 physicalBlock;
  4041.  
  4042. -   while (true) {
  4043. -       size_t length = ext2_dir_entry::MinimumSize();
  4044. -       status_t status = fInode->ReadAt(fOffset, (uint8*)&entry, &length);
  4045. -       if (status != B_OK)
  4046. -           return status;
  4047. -       if (length < ext2_dir_entry::MinimumSize() || entry.Length() == 0)
  4048. +   status_t status = fInode->FindBlock(fBlock * fBlockSize, physicalBlock);
  4049. +   if (status != B_OK)
  4050. +       return status;
  4051. +
  4052. +   const uint8* block = cached.SetTo(physicalBlock);
  4053. +   if (block == NULL)
  4054. +       return B_IO_ERROR;
  4055. +
  4056. +   bool gotEntry = false;
  4057. +   while (!gotEntry) {
  4058. +       TRACE("Checking entry at block %lu, displacement %lu\n", physicalBlock,
  4059. +           fDisplacement);
  4060. +
  4061. +       entry = (ext2_dir_entry*)(block + fDisplacement);
  4062. +
  4063. +       if (entry->Length() == 0) {
  4064. +           TRACE("empty entry.\n");
  4065.             return B_ENTRY_NOT_FOUND;
  4066. -       if (!entry.IsValid())
  4067. +       }
  4068. +       if (!entry->IsValid()) {
  4069. +           TRACE("invalid entry.\n");
  4070.             return B_BAD_DATA;
  4071. +       }
  4072.  
  4073. -       if (entry.NameLength() != 0)
  4074. -           break;
  4075. +       if (entry->NameLength() != 0) {
  4076. +           // Get name
  4077. +           gotEntry = true;
  4078.  
  4079. -       fOffset += entry.Length();
  4080. -       TRACE("DirectoryIterator::GetNext() skipping entry\n");
  4081. -   }
  4082. +           size_t length = entry->NameLength();
  4083.  
  4084. -   TRACE("offset %Ld: entry ino %lu, length %u, name length %u, type %u\n",
  4085. -       fOffset, entry.InodeID(), entry.Length(), entry.NameLength(),
  4086. -       entry.FileType());
  4087. +           TRACE("block %lu, displacement %lu: entry ino %lu, length %u, "
  4088. +               "name length %lu, type %lu\n", fBlock, fDisplacement,
  4089. +               entry->InodeID(), entry->Length(), (uint32)length,
  4090. +               (uint32)entry->FileType());
  4091.  
  4092. -   // read name
  4093. +           if (*_nameLength < length)
  4094. +               length = *_nameLength - 1;
  4095. +           memcpy(name, entry->name, length);
  4096. +           name[length] = '\0';
  4097.  
  4098. -   size_t length = entry.NameLength();
  4099. -   status_t status = fInode->ReadAt(fOffset + ext2_dir_entry::MinimumSize(),
  4100. -       (uint8*)entry.name, &length);
  4101. -   if (status == B_OK) {
  4102. -       if (*_nameLength < length)
  4103. -           length = *_nameLength - 1;
  4104. -       memcpy(name, entry.name, length);
  4105. -       name[length] = '\0';
  4106. +           *_id = entry->InodeID();
  4107. +           *_nameLength = length;
  4108. +       }
  4109.  
  4110. -       *_id = entry.InodeID();
  4111. -       *_nameLength = length;
  4112. +       fDisplacement += entry->Length();
  4113.  
  4114. -       fOffset += entry.Length();
  4115. +       if (fDisplacement == fBlockSize) {
  4116. +           TRACE("Reached end of block\n");
  4117. +
  4118. +           fDisplacement = 0;
  4119. +           fBlock++;
  4120. +
  4121. +           if (!gotEntry) {
  4122. +               status = fInode->FindBlock(fBlock * fBlockSize, physicalBlock);
  4123. +               if (status != B_OK)
  4124. +                   return status;
  4125. +
  4126. +               block = cached.SetTo(physicalBlock);
  4127. +               if (block == NULL)
  4128. +                   return B_IO_ERROR;
  4129. +           }
  4130. +       } else if (fDisplacement > fBlockSize && !gotEntry) {
  4131. +           TRACE("The entry isn't block aligned.\n");
  4132. +           // TODO: Is block alignment obligatory?
  4133. +           return B_BAD_DATA;
  4134. +       }
  4135. +
  4136. +       TRACE("DirectoryIterator::GetNext() skipping entry\n");
  4137.     }
  4138.  
  4139. -   return status;
  4140. +   return B_OK;
  4141.  }
  4142.  
  4143.  
  4144.  status_t
  4145.  DirectoryIterator::Rewind()
  4146.  {
  4147. -   fOffset = 0;
  4148. +   fDisplacement = 0;
  4149. +   fBlock = 0;
  4150. +
  4151.     return B_OK;
  4152.  }
  4153. +
  4154. +
  4155. +status_t
  4156. +DirectoryIterator::AddEntry(Transaction& transaction, char* name,
  4157. +   size_t _nameLength, ino_t id)
  4158. +{
  4159. +   // TODO: Perhaps we should search for an empty spot with enough space for
  4160. +   // the entry, to try to minimize framgentation
  4161. +
  4162. +   /*off_t offset = fInode->Size();
  4163. +   fBlock = FindBlock(offset,
  4164. +   uint8 nameLength = _nameLength > EXT2_NAME_LENGTH ? EXT2_NAME_LENGTH
  4165. +       : _nameLength;
  4166. +
  4167. +   ext2_dir_entry entry;
  4168. +   entry.SetInodeID(id);
  4169. +   entry.SetLength(nameLength);
  4170. +
  4171. +   status_t status = fInode->WriteAt(transaction, fOffset, (uint8*)&entry,
  4172. +       ext2_dir_entry::MinimumSize());
  4173. +   if (status != B_OK)
  4174. +       return status;
  4175. +   return fInode->WriteAt(transaction, fOffset
  4176. +       + ext2_dir_entry::MinimumSize(), name, (size_t)nameLength);*/
  4177. +   return B_OK;
  4178. +}
  4179. Index: src/add-ons/kernel/file_systems/ext2/Journal.h
  4180. ===================================================================
  4181. --- src/add-ons/kernel/file_systems/ext2/Journal.h  (revision 0)
  4182. +++ src/add-ons/kernel/file_systems/ext2/Journal.h  (revision 0)
  4183. @@ -0,0 +1,241 @@
  4184. +/*
  4185. + * Copyright 2001-2010, Haiku Inc. All rights reserved.
  4186. + * This file may be used under the terms of the MIT License.
  4187. + *
  4188. + * Authors:
  4189. + *     Janito V. Ferreira Filho
  4190. + */
  4191. +#ifndef JOURNAL_H
  4192. +#define JOURNAL_H
  4193. +
  4194. +
  4195. +#define JOURNAL_MAGIC                              0xc03b3998U
  4196. +
  4197. +#define JOURNAL_DESCRIPTOR_BLOCK                   1
  4198. +#define JOURNAL_COMMIT_BLOCK                       2
  4199. +#define JOURNAL_SUPERBLOCK_V1                      3
  4200. +#define JOURNAL_SUPERBLOCK_V2                      4
  4201. +#define JOURNAL_REVOKE_BLOCK                       5
  4202. +
  4203. +#define JOURNAL_FLAG_ESCAPED                       1
  4204. +#define JOURNAL_FLAG_SAME_UUID                     2
  4205. +#define JOURNAL_FLAG_DELETED                       4
  4206. +#define JOURNAL_FLAG_LAST_TAG                      8
  4207. +
  4208. +#define JOURNAL_FEATURE_INCOMPATIBLE_REVOKE            1
  4209. +
  4210. +#define JOURNAL_KNOWN_READ_ONLY_COMPATIBLE_FEATURES    0
  4211. +#define JOURNAL_KNOWN_INCOMPATIBLE_FEATURES            \
  4212. +   JOURNAL_FEATURE_INCOMPATIBLE_REVOKE
  4213. +
  4214. +
  4215. +#include "Volume.h"
  4216. +
  4217. +#include <util/DoublyLinkedList.h>
  4218. +
  4219. +#include "Transaction.h"
  4220. +
  4221. +
  4222. +class RevokeManager;
  4223. +
  4224. +
  4225. +struct JournalHeader {
  4226. +   uint32          magic;
  4227. +   uint32          block_type;
  4228. +   uint32          sequence;
  4229. +   char            data[0];
  4230. +
  4231. +   uint32          Magic()         const  
  4232. +       { return B_BENDIAN_TO_HOST_INT32(magic); }
  4233. +   uint32          BlockType()     const  
  4234. +       { return B_BENDIAN_TO_HOST_INT32(block_type); }
  4235. +   uint32          Sequence()      const  
  4236. +       { return B_BENDIAN_TO_HOST_INT32(sequence); }
  4237. +
  4238. +   bool            CheckMagic()    const
  4239. +       { return Magic() == JOURNAL_MAGIC; }
  4240. +
  4241. +   void            MakeDescriptor(uint32 sequence);
  4242. +   void            MakeCommit(uint32 sequence);
  4243. +} _PACKED;
  4244. +
  4245. +
  4246. +struct JournalBlockTag {
  4247. +   uint32          block_number;
  4248. +   uint32          flags;
  4249. +
  4250. +   uint32          BlockNumber()   const  
  4251. +       { return B_BENDIAN_TO_HOST_INT32(block_number); }
  4252. +   uint32          Flags()         const  
  4253. +       { return B_BENDIAN_TO_HOST_INT32(flags); }
  4254. +
  4255. +   void            SetBlockNumber(uint32 block)
  4256. +       { block_number = B_HOST_TO_BENDIAN_INT32(block); }
  4257. +   void            SetFlags(uint32 new_flags)
  4258. +       { flags = B_HOST_TO_BENDIAN_INT32(new_flags); }
  4259. +   void            SetLastTagFlag()
  4260. +       { flags |= B_HOST_TO_BENDIAN_INT32(JOURNAL_FLAG_LAST_TAG); }
  4261. +   void            SetEscapedFlag()
  4262. +       { flags |= B_HOST_TO_BENDIAN_INT32(JOURNAL_FLAG_ESCAPED); }
  4263. +} _PACKED;
  4264. +
  4265. +
  4266. +struct JournalRevokeHeader {
  4267. +   JournalHeader   header;
  4268. +   uint32          num_bytes;
  4269. +
  4270. +   uint32          revoke_blocks[0];
  4271. +
  4272. +   uint32          NumBytes()      const  
  4273. +       { return B_BENDIAN_TO_HOST_INT32(num_bytes); }
  4274. +   uint32          RevokeBlock(int offset) const  
  4275. +       { return B_BENDIAN_TO_HOST_INT32(revoke_blocks[offset]); }
  4276. +} _PACKED;
  4277. +
  4278. +
  4279. +struct JournalSuperBlock {
  4280. +   JournalHeader   header;
  4281. +  
  4282. +   uint32          block_size;
  4283. +   uint32          num_blocks;
  4284. +   uint32          first_log_block;
  4285. +
  4286. +   uint32          first_commit_id;
  4287. +   uint32          log_start;
  4288. +
  4289. +   uint32          error;
  4290. +
  4291. +   uint32          compatible_features;
  4292. +   uint32          incompatible_features;
  4293. +   uint32          read_only_compatible_features;
  4294. +
  4295. +   uint8           uuid[16];
  4296. +
  4297. +   uint32          num_users;
  4298. +   uint32          dynamic_superblock;
  4299. +
  4300. +   uint32          max_transaction_blocks;
  4301. +   uint32          max_transaction_data;
  4302. +
  4303. +   uint32          padding[44];
  4304. +
  4305. +   uint8           user_ids[16*48];
  4306. +
  4307. +   uint32          BlockSize() const
  4308. +       { return B_BENDIAN_TO_HOST_INT32(block_size); }
  4309. +   uint32          NumBlocks() const
  4310. +       { return B_BENDIAN_TO_HOST_INT32(num_blocks); }
  4311. +   uint32          FirstLogBlock() const
  4312. +       { return B_BENDIAN_TO_HOST_INT32(first_log_block); }
  4313. +   uint32          FirstCommitID() const
  4314. +       { return B_BENDIAN_TO_HOST_INT32(first_commit_id); }
  4315. +   uint32          LogStart() const
  4316. +       { return B_BENDIAN_TO_HOST_INT32(compatible_features); }
  4317. +   uint32          IncompatibleFeatures() const
  4318. +       { return B_BENDIAN_TO_HOST_INT32(incompatible_features); }
  4319. +   uint32          ReadOnlyCompatibleFeatures() const
  4320. +       { return B_BENDIAN_TO_HOST_INT32(read_only_compatible_features); }
  4321. +   uint32          MaxTransactionData() const
  4322. +       { return B_BENDIAN_TO_HOST_INT32(max_transaction_data); }
  4323. +
  4324. +   void            SetLogStart(uint32 logStart)
  4325. +       { log_start = B_HOST_TO_BENDIAN_INT32(logStart); }
  4326. +   void            SetFirstCommitID(uint32 firstCommitID)
  4327. +       { first_commit_id = B_HOST_TO_BENDIAN_INT32(firstCommitID); }
  4328. +} _PACKED;
  4329. +
  4330. +class LogEntry;
  4331. +class Transaction;
  4332. +typedef DoublyLinkedList<LogEntry> LogEntryList;
  4333. +
  4334. +
  4335. +class Journal {
  4336. +public:
  4337. +                               Journal(Volume *fsVolume, Volume *jVolume);
  4338. +   virtual                     ~Journal();
  4339. +
  4340. +   virtual status_t            InitCheck();
  4341. +   virtual status_t            Recover();
  4342. +   virtual status_t            StartLog();
  4343. +           status_t            RestartLog();
  4344. +
  4345. +           status_t            Lock(Transaction* owner,
  4346. +                                   bool separateSubTransactions);
  4347. +           status_t            Unlock(Transaction* owner, bool success);
  4348. +
  4349. +   virtual status_t            MapBlock(uint32 logical, uint32& physical);
  4350. +   inline  uint32              FreeLogBlocks() const;
  4351. +          
  4352. +           status_t            FlushLogAndBlocks();
  4353. +
  4354. +           int32               TransactionID() const;
  4355. +
  4356. +           Volume*             GetFilesystemVolume()
  4357. +               { return fFilesystemVolume; }
  4358. +protected:
  4359. +                               Journal();
  4360. +  
  4361. +   virtual status_t            _WriteTransactionToLog();
  4362. +
  4363. +
  4364. +           Volume*             fJournalVolume;
  4365. +           void*               fJournalBlockCache;
  4366. +           Volume*             fFilesystemVolume;
  4367. +           void*               fFilesystemBlockCache;
  4368. +
  4369. +           recursive_lock      fLock;
  4370. +           Transaction*        fOwner;
  4371. +
  4372. +           RevokeManager*      fRevokeManager;
  4373. +
  4374. +           status_t            fInitStatus;
  4375. +           uint32              fBlockSize;
  4376. +           uint32              fFirstCommitID;
  4377. +           uint32              fFirstCacheCommitID;
  4378. +           uint32              fFirstLogBlock;
  4379. +           uint32              fLogSize;
  4380. +           uint32              fVersion;
  4381. +          
  4382. +           uint32              fLogStart;
  4383. +           uint32              fLogEnd;
  4384. +           uint32              fFreeBlocks;
  4385. +           uint32              fMaxTransactionSize;
  4386. +
  4387. +           uint32              fCurrentCommitID;
  4388. +           //uint32                fNextCommitID;
  4389. +
  4390. +           LogEntryList        fLogEntries;
  4391. +           mutex               fLogEntriesLock;
  4392. +           bool                fHasSubTransaction;
  4393. +           bool                fSeparateSubTransactions;
  4394. +           int32               fUnwrittenTransactions;
  4395. +           int32               fTransactionID;
  4396. +
  4397. +private:
  4398. +           status_t            _SaveSuperBlock();
  4399. +           status_t            _LoadSuperBlock();
  4400. +           status_t            _CheckFeatures(JournalSuperBlock* superblock);
  4401. +
  4402. +           uint32              _CountTags(JournalHeader *descriptorBlock);
  4403. +           status_t            _RecoverPassScan(uint32& lastCommitID);
  4404. +           status_t            _RecoverPassRevoke(uint32 lastCommitID);
  4405. +           status_t            _RecoverPassReplay(uint32 lastCommitID);
  4406. +
  4407. +           status_t            _FlushLog(bool canWait, bool flushBlocks);
  4408. +
  4409. +   inline  uint32              _WrapAroundLog(uint32 block);
  4410. +          
  4411. +           size_t              _CurrentTransactionSize() const;
  4412. +           size_t              _FullTransactionSize() const;
  4413. +           size_t              _MainTransactionSize() const;
  4414. +          
  4415. +   virtual status_t            _TransactionDone(bool success);
  4416. +
  4417. +   static  void                _TransactionWritten(int32 transactionID,
  4418. +                                   int32 event, void* _logEntry);
  4419. +   static  void                _TransactionIdle(int32 transactionID,
  4420. +                                   int32 event, void* _journal);
  4421. +};
  4422. +
  4423. +#endif // JOURNAL_H
  4424. +
  4425.  
  4426. Property changes on: src/add-ons/kernel/file_systems/ext2/Journal.h
  4427. ___________________________________________________________________
  4428. Added: svn:executable
  4429.    + *
  4430.  
  4431. Index: src/add-ons/kernel/file_systems/ext2/IndexedDirectoryIterator.h
  4432. ===================================================================
  4433. --- src/add-ons/kernel/file_systems/ext2/IndexedDirectoryIterator.h (revision 37473)
  4434. +++ src/add-ons/kernel/file_systems/ext2/IndexedDirectoryIterator.h (working copy)
  4435. @@ -17,7 +17,7 @@
  4436.  class IndexedDirectoryIterator : public DirectoryIterator {
  4437.  public:
  4438.                                 IndexedDirectoryIterator(off_t start,
  4439. -                                   uint32 blockSize, Inode* directory,
  4440. +                                   Inode* directory,
  4441.                                     HTreeEntryIterator* parent);
  4442.     virtual                     ~IndexedDirectoryIterator();
  4443.    
  4444. @@ -25,12 +25,15 @@
  4445.                                     ino_t* id);
  4446.            
  4447.             status_t            Rewind();
  4448. +
  4449. +           status_t            AddEntry(Transaction& transaction, char* name,
  4450. +                                   size_t _nameLength, ino_t id);
  4451. +
  4452.  private:
  4453.             bool                fIndexing;
  4454.             HTreeEntryIterator* fParent;
  4455. -           off_t               fMaxOffset;
  4456. -           uint32              fBlockSize;
  4457.             uint32              fMaxAttempts;
  4458. +           uint32              fPreviousBlock;
  4459.  };
  4460.  
  4461.  #endif // INDEXED_DIRECTORY_ITERATOR_H
  4462. Index: src/add-ons/kernel/file_systems/ext2/Transaction.cpp
  4463. ===================================================================
  4464. --- src/add-ons/kernel/file_systems/ext2/Transaction.cpp    (revision 0)
  4465. +++ src/add-ons/kernel/file_systems/ext2/Transaction.cpp    (revision 0)
  4466. @@ -0,0 +1,201 @@
  4467. +/*
  4468. + * Copyright 2001-2010, Haiku Inc. All rights reserved.
  4469. + * This file may be used under the terms of the MIT License.
  4470. + *
  4471. + * Authors:
  4472. + *     Janito V. Ferreira Filho
  4473. + */
  4474. +
  4475. +#include "Transaction.h"
  4476. +
  4477. +#include <string.h>
  4478. +
  4479. +#include <fs_cache.h>
  4480. +
  4481. +#include "Journal.h"
  4482. +
  4483. +
  4484. +TransactionListener::TransactionListener()
  4485. +{
  4486. +}
  4487. +
  4488. +
  4489. +TransactionListener::~TransactionListener()
  4490. +{
  4491. +}
  4492. +
  4493. +
  4494. +Transaction::Transaction()
  4495. +   :
  4496. +   fJournal(NULL),
  4497. +   fParent(NULL)
  4498. +{
  4499. +}
  4500. +
  4501. +
  4502. +Transaction::Transaction(Journal* journal)
  4503. +   :
  4504. +   fJournal(NULL),
  4505. +   fParent(NULL)
  4506. +{
  4507. +   Start(journal);
  4508. +}
  4509. +
  4510. +
  4511. +Transaction::~Transaction()
  4512. +{
  4513. +   if (IsStarted())
  4514. +       fJournal->Unlock(this, false);
  4515. +}
  4516. +
  4517. +status_t
  4518. +Transaction::Start(Journal* journal)
  4519. +{
  4520. +   if (IsStarted())
  4521. +       return B_OK;
  4522. +
  4523. +   fJournal = journal;
  4524. +   if (fJournal == NULL)
  4525. +       return B_ERROR;
  4526. +  
  4527. +   status_t status = fJournal->Lock(this, false);
  4528. +   if (status != B_OK)
  4529. +       fJournal = NULL;
  4530. +
  4531. +   return status;
  4532. +}
  4533. +
  4534. +
  4535. +status_t
  4536. +Transaction::Done()
  4537. +{
  4538. +   if (!IsStarted())
  4539. +       return B_OK;
  4540. +
  4541. +   status_t status = fJournal->Unlock(this, true);
  4542. +  
  4543. +   if (status == B_OK)
  4544. +       fJournal = NULL;
  4545. +
  4546. +   return status;
  4547. +}
  4548. +
  4549. +
  4550. +int32
  4551. +Transaction::ID() const
  4552. +{
  4553. +   if (!IsStarted())
  4554. +       return -1;
  4555. +
  4556. +   return fJournal->TransactionID();
  4557. +}
  4558. +
  4559. +
  4560. +bool
  4561. +Transaction::IsStarted() const
  4562. +{
  4563. +   return fJournal != NULL;
  4564. +}
  4565. +
  4566. +
  4567. +bool
  4568. +Transaction::HasParent() const
  4569. +{
  4570. +   return fParent != NULL;
  4571. +}
  4572. +
  4573. +
  4574. +status_t
  4575. +Transaction::WriteBlocks(off_t blockNumber, const uint8* buffer,
  4576. +   size_t numBlocks)
  4577. +{
  4578. +   if (!IsStarted())
  4579. +       return B_NO_INIT;
  4580. +
  4581. +   void* cache = GetVolume()->BlockCache();
  4582. +   size_t blockSize = GetVolume()->BlockSize();
  4583. +
  4584. +   for (size_t i = 0; i < numBlocks; ++i) {
  4585. +       void* block = block_cache_get_empty(cache, blockNumber + i, ID());
  4586. +       if (block == NULL)
  4587. +           return B_ERROR;
  4588. +      
  4589. +       memcpy(block, buffer, blockSize);
  4590. +       buffer += blockSize;
  4591. +
  4592. +       block_cache_put(cache, blockNumber + i);
  4593. +   }
  4594. +
  4595. +   return B_OK;
  4596. +}
  4597. +
  4598. +
  4599. +void
  4600. +Transaction::Split()
  4601. +{
  4602. +   cache_start_sub_transaction(fJournal->GetFilesystemVolume()->BlockCache(),
  4603. +       ID());
  4604. +}
  4605. +
  4606. +
  4607. +Volume*
  4608. +Transaction::GetVolume() const
  4609. +{
  4610. +   if (!IsStarted())
  4611. +       return NULL;
  4612. +
  4613. +   return fJournal->GetFilesystemVolume();
  4614. +}
  4615. +
  4616. +
  4617. +void
  4618. +Transaction::AddListener(TransactionListener* listener)
  4619. +{
  4620. +   if (!IsStarted())
  4621. +       panic("Transaction is not running!");
  4622. +
  4623. +   fListeners.Add(listener);
  4624. +}
  4625. +
  4626. +
  4627. +void
  4628. +Transaction::RemoveListener(TransactionListener* listener)
  4629. +{
  4630. +   if (!IsStarted())
  4631. +       panic("Transaction is not running!");
  4632. +
  4633. +   fListeners.Remove(listener);
  4634. +   listener->RemovedFromTransaction();
  4635. +}
  4636. +
  4637. +
  4638. +void
  4639. +Transaction::NotifyListeners(bool success)
  4640. +{
  4641. +   while (TransactionListener* listener = fListeners.RemoveHead()) {
  4642. +       listener->TransactionDone(success);
  4643. +       listener->RemovedFromTransaction();
  4644. +   }
  4645. +}
  4646. +
  4647. +
  4648. +void
  4649. +Transaction::MoveListenersTo(Transaction* transaction)
  4650. +{
  4651. +   while (TransactionListener* listener = fListeners.RemoveHead())
  4652. +       transaction->fListeners.Add(listener);
  4653. +}
  4654. +
  4655. +
  4656. +void
  4657. +Transaction::SetParent(Transaction* transaction)
  4658. +{
  4659. +   fParent = transaction;
  4660. +}
  4661. +
  4662. +
  4663. +Transaction*
  4664. +Transaction::Parent() const
  4665. +{
  4666. +   return fParent;
  4667. +}
  4668. Index: src/add-ons/kernel/file_systems/ext2/ext2.h
  4669. ===================================================================
  4670. --- src/add-ons/kernel/file_systems/ext2/ext2.h (revision 37473)
  4671. +++ src/add-ons/kernel/file_systems/ext2/ext2.h (working copy)
  4672. @@ -13,6 +13,8 @@
  4673.  #include <KernelExport.h>
  4674.  
  4675.  
  4676. +#define TRACE_EXT2
  4677. +
  4678.  #define EXT2_SUPER_BLOCK_OFFSET    1024
  4679.  
  4680.  struct ext2_super_block {
  4681. @@ -108,9 +110,16 @@
  4682.         { return B_LENDIAN_TO_HOST_INT32(read_only_features); }
  4683.     uint32 IncompatibleFeatures() const
  4684.         { return B_LENDIAN_TO_HOST_INT32(incompatible_features); }
  4685. +   ino_t  JournalInode() const
  4686. +       { return B_LENDIAN_TO_HOST_INT32(journal_inode); }
  4687.     uint32 HashSeed(uint8 i) const
  4688.         { return B_LENDIAN_TO_HOST_INT32(hash_seed[i]); }
  4689.  
  4690. +   void SetFreeInodes(uint32 freeInodes)
  4691. +       { free_inodes = B_HOST_TO_LENDIAN_INT32(freeInodes); }
  4692. +   void SetFreeBlocks(uint32 freeBlocks)
  4693. +       { free_blocks = B_HOST_TO_LENDIAN_INT32(freeBlocks); }
  4694. +
  4695.     bool IsValid();
  4696.         // implemented in Volume.cpp
  4697.  } _PACKED;
  4698. @@ -162,8 +171,16 @@
  4699.     uint16  _padding;
  4700.     uint32  _reserved[3];
  4701.  
  4702. +   uint32 BlockBitmap() const
  4703. +       { return B_LENDIAN_TO_HOST_INT32(block_bitmap); }
  4704. +   uint32 InodeBitmap() const
  4705. +       { return B_LENDIAN_TO_HOST_INT32(inode_bitmap); }
  4706.     uint32 InodeTable() const
  4707.         { return B_LENDIAN_TO_HOST_INT32(inode_table); }
  4708. +   uint16 FreeBlocks() const
  4709. +       { return B_LENDIAN_TO_HOST_INT16(free_blocks); }
  4710. +   uint16 FreeInodes() const
  4711. +       { return B_LENDIAN_TO_HOST_INT16(free_inodes); }
  4712.  } _PACKED;
  4713.  
  4714.  #define EXT2_DIRECT_BLOCKS         12
  4715. @@ -214,6 +231,7 @@
  4716.     uint16 Mode() const { return B_LENDIAN_TO_HOST_INT16(mode); }
  4717.     uint32 Flags() const { return B_LENDIAN_TO_HOST_INT32(flags); }
  4718.     uint16 NumLinks() const { return B_LENDIAN_TO_HOST_INT16(num_links); }
  4719. +   uint32 NumBlocks() const { return B_LENDIAN_TO_HOST_INT32(num_blocks); }
  4720.  
  4721.     time_t AccessTime() const { return B_LENDIAN_TO_HOST_INT32(access_time); }
  4722.     time_t CreationTime() const { return B_LENDIAN_TO_HOST_INT32(creation_time); }
  4723. @@ -270,11 +288,26 @@
  4724.     uint8   file_type;
  4725.     char    name[EXT2_NAME_LENGTH];
  4726.  
  4727. -   uint32 InodeID() const { return B_LENDIAN_TO_HOST_INT32(inode_id); }
  4728. -   uint16 Length() const { return B_LENDIAN_TO_HOST_INT16(length); }
  4729. -   uint8 NameLength() const { return name_length; }
  4730. -   uint8 FileType() const { return file_type; }
  4731. +   uint32  InodeID() const { return B_LENDIAN_TO_HOST_INT32(inode_id); }
  4732. +   uint16  Length() const { return B_LENDIAN_TO_HOST_INT16(length); }
  4733. +   uint8   NameLength() const { return name_length; }
  4734. +   uint8   FileType() const { return file_type; }
  4735.  
  4736. +   void    SetInodeID(uint32 id) { inode_id = B_HOST_TO_LENDIAN_INT32(id); }
  4737. +
  4738. +   void    SetLength(uint8 nameLength)
  4739. +   {
  4740. +       name_length = nameLength;
  4741. +
  4742. +       if (nameLength % 4 == 0) {
  4743. +           length = B_HOST_TO_LENDIAN_INT16(
  4744. +               (short)(nameLength + MinimumSize()));
  4745. +       } else {
  4746. +           length = B_HOST_TO_LENDIAN_INT16(
  4747. +               (short)(nameLength % 4 + 1 + MinimumSize()));
  4748. +       }
  4749. +   }
  4750. +
  4751.     bool IsValid() const
  4752.     {
  4753.         return Length() > MinimumSize();
  4754. Index: src/add-ons/kernel/file_systems/ext2/CachedBlock.h
  4755. ===================================================================
  4756. --- src/add-ons/kernel/file_systems/ext2/CachedBlock.h  (revision 37473)
  4757. +++ src/add-ons/kernel/file_systems/ext2/CachedBlock.h  (working copy)
  4758. @@ -9,32 +9,40 @@
  4759.  
  4760.  #include <fs_cache.h>
  4761.  
  4762. +#include "Transaction.h"
  4763.  #include "Volume.h"
  4764.  
  4765.  
  4766.  class CachedBlock {
  4767.  public:
  4768. -                   CachedBlock(Volume* volume);
  4769. -                   CachedBlock(Volume* volume, uint32 block);
  4770. -                   ~CachedBlock();
  4771. +                           CachedBlock(Volume* volume);
  4772. +                           CachedBlock(Volume* volume, uint32 block);
  4773. +                           ~CachedBlock();
  4774.  
  4775. -           void    Keep();
  4776. -           void    Unset();
  4777. +           void            Keep();
  4778. +           void            Unset();
  4779.  
  4780. -   const   uint8*  SetTo(uint32 block);
  4781. +           const uint8*    SetTo(uint32 block);
  4782. +           uint8*          SetToWritable(Transaction& transaction,
  4783. +                               uint32 block, bool empty = false);
  4784. +           uint8*          SetToWritableWithoutTransaction(uint32 block,
  4785. +                               bool empty = false);
  4786.  
  4787. -   const   uint8*  Block() const { return fBlock; }
  4788. -           off_t   BlockNumber() const { return fBlockNumber; }
  4789. +           const uint8*    Block() const { return fBlock; }
  4790. +           off_t           BlockNumber() const { return fBlockNumber; }
  4791.  
  4792.  private:
  4793. -                   CachedBlock(const CachedBlock &);
  4794. -                   CachedBlock &operator=(const CachedBlock &);
  4795. -                       // no implementation
  4796. +                           CachedBlock(const CachedBlock &);
  4797. +                           CachedBlock &operator=(const CachedBlock &);
  4798. +                               // no implementation
  4799. +                      
  4800. +           uint8*          _SetToWritableEtc(int32 transaction, uint32 block,
  4801. +                               bool empty);
  4802.  
  4803.  protected:
  4804. -   Volume*         fVolume;
  4805. -   uint32          fBlockNumber;
  4806. -   uint8*          fBlock;
  4807. +           Volume*         fVolume;
  4808. +           uint32          fBlockNumber;
  4809. +           uint8*          fBlock;
  4810.  };
  4811.  
  4812.  
  4813. @@ -94,4 +102,35 @@
  4814.     return fBlock = (uint8 *)block_cache_get(fVolume->BlockCache(), block);
  4815.  }
  4816.  
  4817. +
  4818. +inline uint8*
  4819. +CachedBlock::SetToWritable(Transaction& transaction, uint32 block, bool empty)
  4820. +{
  4821. +   return _SetToWritableEtc(transaction.ID(), block, empty);
  4822. +}
  4823. +
  4824. +
  4825. +inline uint8*
  4826. +CachedBlock::SetToWritableWithoutTransaction(uint32 block, bool empty)
  4827. +{
  4828. +   return _SetToWritableEtc((int32)-1, block, empty);
  4829. +}
  4830. +
  4831. +inline uint8*
  4832. +CachedBlock::_SetToWritableEtc(int32 transaction, uint32 block, bool empty)
  4833. +{
  4834. +   Unset();
  4835. +   fBlockNumber = block;
  4836. +
  4837. +   if (empty) {
  4838. +       fBlock = (uint8*)block_cache_get_empty(fVolume->BlockCache(),
  4839. +           block, transaction);
  4840. +   } else {
  4841. +       fBlock = (uint8*)block_cache_get_writable(fVolume->BlockCache(),
  4842. +           block, transaction);
  4843. +   }
  4844. +
  4845. +   return fBlock;
  4846. +}
  4847. +
  4848.  #endif // CACHED_BLOCK_H
  4849. Index: src/add-ons/kernel/file_systems/ext2/HashRevokeManager.cpp
  4850. ===================================================================
  4851. --- src/add-ons/kernel/file_systems/ext2/HashRevokeManager.cpp  (revision 0)
  4852. +++ src/add-ons/kernel/file_systems/ext2/HashRevokeManager.cpp  (revision 0)
  4853. @@ -0,0 +1,141 @@
  4854. +/*
  4855. + * Copyright 2001-2010, Haiku Inc. All rights reserved.
  4856. + * This file may be used under the terms of the MIT License.
  4857. + *
  4858. + * Authors:
  4859. + *     Janito V. Ferreira Filho
  4860. + */
  4861. +
  4862. +#include "HashRevokeManager.h"
  4863. +
  4864. +#include <new>
  4865. +
  4866. +
  4867. +HashRevokeManager::HashRevokeManager()
  4868. +   :
  4869. +   kInitialHashSize(128)
  4870. +       // TODO: Benchmark and find an optimal value
  4871. +{
  4872. +}
  4873. +
  4874. +
  4875. +HashRevokeManager::~HashRevokeManager()
  4876. +{
  4877. +   hash_uninit(fHash);
  4878. +}
  4879. +
  4880. +
  4881. +status_t
  4882. +HashRevokeManager::Init()
  4883. +{
  4884. +   RevokeElement dummyElement;
  4885. +  
  4886. +   fHash = hash_init(kInitialHashSize, offset_of_member(dummyElement, next),
  4887. +       &HashRevokeManager::Compare,
  4888. +       &HashRevokeManager::Hash);
  4889. +
  4890. +   if (fHash == NULL)
  4891. +       return B_NO_MEMORY;
  4892. +
  4893. +   return B_OK;
  4894. +}
  4895. +
  4896. +
  4897. +status_t
  4898. +HashRevokeManager::Insert(uint32 block, uint32 commitID)
  4899. +{
  4900. +   RevokeElement* element = (RevokeElement*)hash_lookup(fHash, &block);
  4901. +  
  4902. +   if (element != NULL) {
  4903. +       if (element->commitID < commitID) {
  4904. +           status_t retValue = hash_remove(fHash, element);
  4905. +          
  4906. +           if (retValue != B_OK)
  4907. +               return retValue;
  4908. +
  4909. +           delete element;
  4910. +       }
  4911. +       else {
  4912. +           return B_OK;
  4913. +               // We already have a newer version of the block
  4914. +       }
  4915. +   }
  4916. +
  4917. +   return _ForceInsert(block, commitID);
  4918. +}
  4919. +
  4920. +
  4921. +status_t
  4922. +HashRevokeManager::Remove(uint32 block)
  4923. +{
  4924. +   RevokeElement* element = (RevokeElement*)hash_lookup(fHash, &block);
  4925. +
  4926. +   if (element == NULL)
  4927. +       return B_ERROR; // TODO: Perhaps we should just ignore?
  4928. +
  4929. +   status_t retValue = hash_remove(fHash, element);
  4930. +  
  4931. +   if (retValue == B_OK)
  4932. +       delete element;
  4933. +
  4934. +   return retValue;
  4935. +}
  4936. +
  4937. +
  4938. +bool
  4939. +HashRevokeManager::Lookup(uint32 block, uint32 commitID)
  4940. +{
  4941. +   RevokeElement* element = (RevokeElement*)hash_lookup(fHash, &block);
  4942. +
  4943. +   if (element == NULL)
  4944. +       return false;
  4945. +
  4946. +   return element->commitID >= commitID;
  4947. +}
  4948. +
  4949. +
  4950. +/*static*/ int
  4951. +HashRevokeManager::Compare(void* _revoked, const void *_block)
  4952. +{
  4953. +   RevokeElement* revoked = (RevokeElement*)_revoked;
  4954. +   uint32 block = *(uint32*)_block;
  4955. +
  4956. +   if (revoked->block == block)
  4957. +       return 0;
  4958. +
  4959. +   return (revoked->block > block) ? 1 : -1;
  4960. +}
  4961. +
  4962. +
  4963. +/*static*/ uint32
  4964. +HashRevokeManager::Hash(void* _revoked, const void* _block, uint32 range)
  4965. +{
  4966. +   RevokeElement* revoked = (RevokeElement*)revoked;
  4967. +   uint32 block = *(uint32*)_block;
  4968. +
  4969. +   if (revoked != NULL)
  4970. +       return revoked->block % range;
  4971. +
  4972. +   return block % range;
  4973. +}
  4974. +
  4975. +
  4976. +status_t
  4977. +HashRevokeManager::_ForceInsert(uint32 block, uint32 commitID)
  4978. +{
  4979. +   RevokeElement* element = new(std::nothrow) RevokeElement;
  4980. +
  4981. +   if (element == NULL)
  4982. +       return B_NO_MEMORY;
  4983. +
  4984. +   element->block = block;
  4985. +   element->commitID = commitID;
  4986. +
  4987. +   status_t retValue = hash_insert_grow(fHash, element);
  4988. +
  4989. +   if (retValue == B_OK)
  4990. +       fRevokeCount++;
  4991. +
  4992. +   return retValue;
  4993. +}
  4994. +
  4995.  
  4996. Property changes on: src/add-ons/kernel/file_systems/ext2/HashRevokeManager.cpp
  4997. ___________________________________________________________________
  4998. Added: svn:executable
  4999.    + *
  5000.  
  5001. Index: src/add-ons/kernel/file_systems/ext2/RevokeManager.h
  5002. ===================================================================
  5003. --- src/add-ons/kernel/file_systems/ext2/RevokeManager.h    (revision 0)
  5004. +++ src/add-ons/kernel/file_systems/ext2/RevokeManager.h    (revision 0)
  5005. @@ -0,0 +1,35 @@
  5006. +/*
  5007. + * Copyright 2001-2010, Haiku Inc. All rights reserved.
  5008. + * This file may be used under the terms of the MIT License.
  5009. + *
  5010. + * Authors:
  5011. + *     Janito V. Ferreira Filho
  5012. + */
  5013. +#ifndef REVOKEMANAGER_H
  5014. +#define REVOKEMANAGER_H
  5015. +
  5016. +#include "Journal.h"
  5017. +
  5018. +
  5019. +struct JournalRevokeHeader;
  5020. +
  5021. +class RevokeManager {
  5022. +public:
  5023. +                       RevokeManager();
  5024. +   virtual             ~RevokeManager() = 0;
  5025. +
  5026. +   virtual status_t    Insert(uint32 block, uint32 commitID) = 0;
  5027. +   virtual status_t    Remove(uint32 block) = 0;
  5028. +   virtual bool        Lookup(uint32 block, uint32 commitID) = 0;
  5029. +          
  5030. +           uint32      NumRevokes() { return fRevokeCount; }
  5031. +
  5032. +           status_t    ScanRevokeBlock(JournalRevokeHeader* revokeBlock,
  5033. +                           uint32 commitID);
  5034. +
  5035. +protected:
  5036. +           uint32      fRevokeCount;
  5037. +};
  5038. +
  5039. +#endif // REVOKEMANAGER_H
  5040. +
  5041.  
  5042. Property changes on: src/add-ons/kernel/file_systems/ext2/RevokeManager.h
  5043. ___________________________________________________________________
  5044. Added: svn:executable
  5045.    + *
  5046.  
  5047. Index: src/add-ons/kernel/file_systems/ext2/BitmapBlock.h
  5048. ===================================================================
  5049. --- src/add-ons/kernel/file_systems/ext2/BitmapBlock.h  (revision 0)
  5050. +++ src/add-ons/kernel/file_systems/ext2/BitmapBlock.h  (revision 0)
  5051. @@ -0,0 +1,48 @@
  5052. +/*
  5053. + * Copyright 2001-2010, Haiku Inc. All rights reserved.
  5054. + * This file may be used under the terms of the MIT License.
  5055. + *
  5056. + * Authors:
  5057. + *     Janito V. Ferreira Filho
  5058. + */
  5059. +#ifndef BITMAPBLOCK_H
  5060. +#define BITMAPBLOCK_H
  5061. +
  5062. +#include "CachedBlock.h"
  5063. +
  5064. +
  5065. +class BitmapBlock : public CachedBlock {
  5066. +public:
  5067. +                           BitmapBlock(Volume* volume, uint32 numBits);
  5068. +                           ~BitmapBlock();
  5069. +
  5070. +           bool            SetTo(uint32 block);
  5071. +           bool            SetToWritable(Transaction& transaction,
  5072. +                               uint32 block, bool empty = false);
  5073. +
  5074. +           bool            CheckMarked(uint32 start, uint32 length);
  5075. +           bool            CheckUnmarked(uint32 start, uint32 length);
  5076. +
  5077. +           bool            Mark(uint32 start, uint32 length,
  5078. +                               bool force = false);
  5079. +           bool            Unmark(uint32 start, uint32 length,
  5080. +                               bool force = false);
  5081. +
  5082. +           void            FindNextMarked(uint32& pos);
  5083. +           void            FindNextUnmarked(uint32& pos);
  5084. +
  5085. +           void            FindPreviousMarked(uint32& pos);
  5086. +
  5087. +           void            FindLargestUnmarkedRange(uint32& start,
  5088. +                               uint32& length);
  5089. +
  5090. +           uint32          NumBits() const;
  5091. +
  5092. +protected:
  5093. +           uint32*         fData;
  5094. +           const uint32*   fReadOnlyData;
  5095. +
  5096. +           uint32          fNumBits;
  5097. +};
  5098. +
  5099. +#endif // BITMAPBLOCK_H
  5100.  
  5101. Property changes on: src/add-ons/kernel/file_systems/ext2/BitmapBlock.h
  5102. ___________________________________________________________________
  5103. Added: svn:executable
  5104.    + *
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement