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:
parent
1750cd1e92
commit
c1320b3a33
|
@ -18,6 +18,7 @@ KernelAddon btrfs :
|
||||||
DirectoryIterator.cpp
|
DirectoryIterator.cpp
|
||||||
ExtentAllocator.cpp
|
ExtentAllocator.cpp
|
||||||
Inode.cpp
|
Inode.cpp
|
||||||
|
Journal.cpp
|
||||||
Volume.cpp
|
Volume.cpp
|
||||||
: kernel_libz.a
|
: kernel_libz.a
|
||||||
;
|
;
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
|
@ -13,6 +13,7 @@
|
||||||
#include "CachedBlock.h"
|
#include "CachedBlock.h"
|
||||||
#include "Chunk.h"
|
#include "Chunk.h"
|
||||||
#include "Inode.h"
|
#include "Inode.h"
|
||||||
|
#include "Journal.h"
|
||||||
#include "ExtentAllocator.h"
|
#include "ExtentAllocator.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -387,6 +388,11 @@ Volume::Mount(const char* deviceName, uint32 flags)
|
||||||
fChecksumTree->SetRoot(root->LogicalAddress(), NULL);
|
fChecksumTree->SetRoot(root->LogicalAddress(), NULL);
|
||||||
free(root);
|
free(root);
|
||||||
|
|
||||||
|
// Initialize Journal
|
||||||
|
fJournal = new(std::nothrow) Journal(this);
|
||||||
|
if (fJournal == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
// Initialize ExtentAllocator;
|
// Initialize ExtentAllocator;
|
||||||
fExtentAllocator = new(std::nothrow) ExtentAllocator(this);
|
fExtentAllocator = new(std::nothrow) ExtentAllocator(this);
|
||||||
if (fExtentAllocator == NULL)
|
if (fExtentAllocator == NULL)
|
||||||
|
@ -445,6 +451,7 @@ Volume::Unmount()
|
||||||
delete fChecksumTree;
|
delete fChecksumTree;
|
||||||
delete fFSTree;
|
delete fFSTree;
|
||||||
delete fDevTree;
|
delete fDevTree;
|
||||||
|
delete fJournal;
|
||||||
delete fExtentAllocator;
|
delete fExtentAllocator;
|
||||||
fRootTree = NULL;
|
fRootTree = NULL;
|
||||||
fExtentTree = NULL;
|
fExtentTree = NULL;
|
||||||
|
@ -452,6 +459,7 @@ Volume::Unmount()
|
||||||
fChecksumTree = NULL;
|
fChecksumTree = NULL;
|
||||||
fFSTree = NULL;
|
fFSTree = NULL;
|
||||||
fDevTree = NULL;
|
fDevTree = NULL;
|
||||||
|
fJournal = NULL;
|
||||||
fExtentAllocator = NULL;
|
fExtentAllocator = NULL;
|
||||||
|
|
||||||
TRACE("Volume::Unmount(): Putting root node\n");
|
TRACE("Volume::Unmount(): Putting root node\n");
|
||||||
|
|
|
@ -17,6 +17,8 @@ enum volume_flags {
|
||||||
class BTree;
|
class BTree;
|
||||||
class Chunk;
|
class Chunk;
|
||||||
class Inode;
|
class Inode;
|
||||||
|
class Journal;
|
||||||
|
class Transaction;
|
||||||
class ExtentAllocator;
|
class ExtentAllocator;
|
||||||
|
|
||||||
|
|
||||||
|
@ -46,6 +48,7 @@ public:
|
||||||
uint32 SectorSize() const { return fSectorSize; }
|
uint32 SectorSize() const { return fSectorSize; }
|
||||||
uint32 BlockSize() const { return fBlockSize; }
|
uint32 BlockSize() const { return fBlockSize; }
|
||||||
Chunk* SystemChunk() const { return fChunk; }
|
Chunk* SystemChunk() const { return fChunk; }
|
||||||
|
Journal* GetJournal() const { return fJournal; }
|
||||||
ExtentAllocator* GetAllocator() const { return fExtentAllocator; }
|
ExtentAllocator* GetAllocator() const { return fExtentAllocator; }
|
||||||
|
|
||||||
btrfs_super_block& SuperBlock() { return fSuperBlock; }
|
btrfs_super_block& SuperBlock() { return fSuperBlock; }
|
||||||
|
@ -76,6 +79,7 @@ private:
|
||||||
|
|
||||||
ExtentAllocator* fExtentAllocator;
|
ExtentAllocator* fExtentAllocator;
|
||||||
Chunk* fChunk;
|
Chunk* fChunk;
|
||||||
|
Journal* fJournal;
|
||||||
BTree* fChunkTree;
|
BTree* fChunkTree;
|
||||||
BTree* fRootTree;
|
BTree* fRootTree;
|
||||||
BTree* fDevTree;
|
BTree* fDevTree;
|
||||||
|
|
|
@ -44,6 +44,7 @@ local btrfsSources =
|
||||||
DirectoryIterator.cpp
|
DirectoryIterator.cpp
|
||||||
ExtentAllocator.cpp
|
ExtentAllocator.cpp
|
||||||
Inode.cpp
|
Inode.cpp
|
||||||
|
Journal.cpp
|
||||||
Volume.cpp
|
Volume.cpp
|
||||||
kernel_interface.cpp
|
kernel_interface.cpp
|
||||||
;
|
;
|
||||||
|
|
Loading…
Reference in New Issue