BTRFS: Implement a simple journaling approach, this is not finished and mostly satisfy the need for passing Transaction object for many functions.

Some details about the current Journal:
* Journal can only end transaction.
* It holds a transaction id of fs (fCurrentGeneration) that increments each time a transaction starts.
* _TransactionWritten now just printing message.

Signed-off-by: Augustin Cavalier <waddlesplash@gmail.com>
This commit is contained in:
hyche 2017-08-24 01:38:54 +07:00 committed by Augustin Cavalier
parent 1750cd1e92
commit c1320b3a33
6 changed files with 233 additions and 0 deletions

View File

@ -18,6 +18,7 @@ KernelAddon btrfs :
DirectoryIterator.cpp
ExtentAllocator.cpp
Inode.cpp
Journal.cpp
Volume.cpp
: kernel_libz.a
;

View File

@ -0,0 +1,162 @@
#include "Journal.h"
//#define TRACE_BTRFS
#ifdef TRACE_BTRFS
# define TRACE(x...) dprintf("\33[34mbtrfs:\33[0m " x)
#else
# define TRACE(x...) ;
#endif
# define ERROR(x...) dprintf("\33[34mbtrfs:\33[0m " x)
Journal::Journal(Volume* volume)
:
fVolume(volume),
fOwner(NULL),
fTransactionID(0),
fCurrentGeneration(volume->SuperBlock().Generation())
{
recursive_lock_init(&fLock, "btrfs journal");
}
Journal::~Journal()
{
recursive_lock_destroy(&fLock);
}
/*static*/ void
Journal::_TransactionWritten(int32 transactionID, int32 event, void* _journal)
{
TRACE("TRANSACTION WRITTEN id %i\n", transactionID);
}
status_t
Journal::_TransactionDone(bool success)
{
if (!success) {
cache_abort_transaction(fVolume->BlockCache(), fTransactionID);
return B_OK;
}
cache_end_transaction(fVolume->BlockCache(), fTransactionID,
&_TransactionWritten, this);
//cache_sync_transaction(fVolume->BlockCache(), fTransactionID);
return B_OK;
}
status_t
Journal::Lock(Transaction* owner)
{
status_t status = recursive_lock_lock(&fLock);
if (status != B_OK)
return status;
if (recursive_lock_get_recursion(&fLock) > 1) {
// we'll just use the current transaction again
return B_OK;
}
if (owner != NULL)
owner->SetParent(fOwner);
fOwner = owner;
if (fOwner != NULL) {
fTransactionID = cache_start_transaction(fVolume->BlockCache());
if (fTransactionID < B_OK) {
recursive_lock_unlock(&fLock);
return fTransactionID;
}
fCurrentGeneration++;
TRACE("Journal::Lock() start transaction id: %i\n", fTransactionID);
}
return B_OK;
}
status_t
Journal::UnLock(Transaction* owner, bool success)
{
if (recursive_lock_get_recursion(&fLock) == 1) {
if (owner != NULL) {
status_t status = _TransactionDone(success);
if (status != B_OK)
return status;
fOwner = owner->Parent();
} else {
fOwner = NULL;
}
}
recursive_lock_unlock(&fLock);
return B_OK;
}
// Transaction
Transaction::Transaction(Volume* volume)
:
fJournal(NULL),
fParent(NULL)
{
Start(volume);
}
Transaction::Transaction()
:
fJournal(NULL),
fParent(NULL)
{
}
Transaction::~Transaction()
{
if (fJournal != NULL) {
fJournal->UnLock(this, false);
}
}
bool
Transaction::HasBlock(fsblock_t blockNumber) const
{
return cache_has_block_in_transaction(fJournal->GetVolume()->BlockCache(),
ID(), blockNumber);
}
status_t
Transaction::Start(Volume* volume)
{
if (fJournal != NULL)
return B_OK;
fJournal = volume->GetJournal();
if (fJournal != NULL && fJournal->Lock(this) == B_OK) {
return B_OK;
}
fJournal = NULL;
return B_ERROR;
}
status_t
Transaction::Done()
{
status_t status = B_OK;
if (fJournal != NULL) {
status = fJournal->UnLock(this, true);
if (status == B_OK)
fJournal = NULL;
}
return status;
}

View File

@ -0,0 +1,57 @@
#ifndef JOURNAL_H
#define JOURNAL_H
#include "Volume.h"
class Transaction;
class Journal {
public:
Journal(Volume* volume);
~Journal();
Volume* GetVolume() const { return fVolume; }
Transaction* CurrentTransaction() const { return fOwner; }
uint64 SystemTransactionID() const
{ return fCurrentGeneration; }
int32 TransactionID() const { return fTransactionID; }
status_t Lock(Transaction* owner);
status_t UnLock(Transaction* owner, bool success);
private:
static void _TransactionWritten(int32 transactionID, int32 event,
void* _journal);
status_t _TransactionDone(bool success);
private:
Volume* fVolume;
recursive_lock fLock;
Transaction* fOwner;
int32 fTransactionID;
uint64 fCurrentGeneration;
};
class Transaction {
public:
Transaction(Volume* volume);
Transaction();
~Transaction();
int32 ID() const { return fJournal->TransactionID(); }
uint64 SystemID() const
{ return fJournal->SystemTransactionID(); }
bool HasBlock(fsblock_t blockNumber) const;
Transaction* Parent() const { return fParent; }
void SetParent(Transaction* parent) { fParent = parent; }
status_t Start(Volume* volume);
status_t Done();
private:
Journal* fJournal;
Transaction* fParent;
};
#endif // JOURNAL_H

View File

@ -13,6 +13,7 @@
#include "CachedBlock.h"
#include "Chunk.h"
#include "Inode.h"
#include "Journal.h"
#include "ExtentAllocator.h"
@ -387,6 +388,11 @@ Volume::Mount(const char* deviceName, uint32 flags)
fChecksumTree->SetRoot(root->LogicalAddress(), NULL);
free(root);
// Initialize Journal
fJournal = new(std::nothrow) Journal(this);
if (fJournal == NULL)
return B_NO_MEMORY;
// Initialize ExtentAllocator;
fExtentAllocator = new(std::nothrow) ExtentAllocator(this);
if (fExtentAllocator == NULL)
@ -445,6 +451,7 @@ Volume::Unmount()
delete fChecksumTree;
delete fFSTree;
delete fDevTree;
delete fJournal;
delete fExtentAllocator;
fRootTree = NULL;
fExtentTree = NULL;
@ -452,6 +459,7 @@ Volume::Unmount()
fChecksumTree = NULL;
fFSTree = NULL;
fDevTree = NULL;
fJournal = NULL;
fExtentAllocator = NULL;
TRACE("Volume::Unmount(): Putting root node\n");

View File

@ -17,6 +17,8 @@ enum volume_flags {
class BTree;
class Chunk;
class Inode;
class Journal;
class Transaction;
class ExtentAllocator;
@ -46,6 +48,7 @@ public:
uint32 SectorSize() const { return fSectorSize; }
uint32 BlockSize() const { return fBlockSize; }
Chunk* SystemChunk() const { return fChunk; }
Journal* GetJournal() const { return fJournal; }
ExtentAllocator* GetAllocator() const { return fExtentAllocator; }
btrfs_super_block& SuperBlock() { return fSuperBlock; }
@ -76,6 +79,7 @@ private:
ExtentAllocator* fExtentAllocator;
Chunk* fChunk;
Journal* fJournal;
BTree* fChunkTree;
BTree* fRootTree;
BTree* fDevTree;

View File

@ -44,6 +44,7 @@ local btrfsSources =
DirectoryIterator.cpp
ExtentAllocator.cpp
Inode.cpp
Journal.cpp
Volume.cpp
kernel_interface.cpp
;