From c1320b3a33417a6702471014dac9d089c7036bc3 Mon Sep 17 00:00:00 2001 From: hyche Date: Thu, 24 Aug 2017 01:38:54 +0700 Subject: [PATCH] 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 --- src/add-ons/kernel/file_systems/btrfs/Jamfile | 1 + .../kernel/file_systems/btrfs/Journal.cpp | 162 ++++++++++++++++++ .../kernel/file_systems/btrfs/Journal.h | 57 ++++++ .../kernel/file_systems/btrfs/Volume.cpp | 8 + .../kernel/file_systems/btrfs/Volume.h | 4 + src/tools/btrfs_shell/Jamfile | 1 + 6 files changed, 233 insertions(+) create mode 100644 src/add-ons/kernel/file_systems/btrfs/Journal.cpp create mode 100644 src/add-ons/kernel/file_systems/btrfs/Journal.h diff --git a/src/add-ons/kernel/file_systems/btrfs/Jamfile b/src/add-ons/kernel/file_systems/btrfs/Jamfile index 78ba20ca96..1c76f14ad3 100644 --- a/src/add-ons/kernel/file_systems/btrfs/Jamfile +++ b/src/add-ons/kernel/file_systems/btrfs/Jamfile @@ -18,6 +18,7 @@ KernelAddon btrfs : DirectoryIterator.cpp ExtentAllocator.cpp Inode.cpp + Journal.cpp Volume.cpp : kernel_libz.a ; diff --git a/src/add-ons/kernel/file_systems/btrfs/Journal.cpp b/src/add-ons/kernel/file_systems/btrfs/Journal.cpp new file mode 100644 index 0000000000..ed505d6567 --- /dev/null +++ b/src/add-ons/kernel/file_systems/btrfs/Journal.cpp @@ -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; +} diff --git a/src/add-ons/kernel/file_systems/btrfs/Journal.h b/src/add-ons/kernel/file_systems/btrfs/Journal.h new file mode 100644 index 0000000000..a6272c3174 --- /dev/null +++ b/src/add-ons/kernel/file_systems/btrfs/Journal.h @@ -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 diff --git a/src/add-ons/kernel/file_systems/btrfs/Volume.cpp b/src/add-ons/kernel/file_systems/btrfs/Volume.cpp index 3ed2f2de1a..ee2cf118cb 100644 --- a/src/add-ons/kernel/file_systems/btrfs/Volume.cpp +++ b/src/add-ons/kernel/file_systems/btrfs/Volume.cpp @@ -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"); diff --git a/src/add-ons/kernel/file_systems/btrfs/Volume.h b/src/add-ons/kernel/file_systems/btrfs/Volume.h index a4b292ceae..4f9acf52cc 100644 --- a/src/add-ons/kernel/file_systems/btrfs/Volume.h +++ b/src/add-ons/kernel/file_systems/btrfs/Volume.h @@ -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; diff --git a/src/tools/btrfs_shell/Jamfile b/src/tools/btrfs_shell/Jamfile index 99231c85b3..8ec1718d85 100644 --- a/src/tools/btrfs_shell/Jamfile +++ b/src/tools/btrfs_shell/Jamfile @@ -44,6 +44,7 @@ local btrfsSources = DirectoryIterator.cpp ExtentAllocator.cpp Inode.cpp + Journal.cpp Volume.cpp kernel_interface.cpp ;