1*99768086Shyche /* 2*99768086Shyche * Copyright 2017, Chế Vũ Gia Hy, cvghy116@gmail.com. 3*99768086Shyche * Copyright 2001-2012, Axel Dörfler, axeld@pinc-software.de. 4*99768086Shyche * This file may be used under the terms of the MIT License. 5*99768086Shyche */ 6*99768086Shyche 7*99768086Shyche 8c1320b3aShyche #include "Journal.h" 9c1320b3aShyche 10c1320b3aShyche 11c1320b3aShyche //#define TRACE_BTRFS 12c1320b3aShyche #ifdef TRACE_BTRFS 13c1320b3aShyche # define TRACE(x...) dprintf("\33[34mbtrfs:\33[0m " x) 14c1320b3aShyche #else 15c1320b3aShyche # define TRACE(x...) ; 16c1320b3aShyche #endif 17c1320b3aShyche # define ERROR(x...) dprintf("\33[34mbtrfs:\33[0m " x) 18c1320b3aShyche 19c1320b3aShyche 20c1320b3aShyche Journal::Journal(Volume* volume) 21c1320b3aShyche : 22c1320b3aShyche fVolume(volume), 23c1320b3aShyche fOwner(NULL), 24c1320b3aShyche fTransactionID(0), 25c1320b3aShyche fCurrentGeneration(volume->SuperBlock().Generation()) 26c1320b3aShyche { 27c1320b3aShyche recursive_lock_init(&fLock, "btrfs journal"); 28c1320b3aShyche } 29c1320b3aShyche 30c1320b3aShyche 31c1320b3aShyche Journal::~Journal() 32c1320b3aShyche { 33c1320b3aShyche recursive_lock_destroy(&fLock); 34c1320b3aShyche } 35c1320b3aShyche 36c1320b3aShyche 37c1320b3aShyche /*static*/ void 38c1320b3aShyche Journal::_TransactionWritten(int32 transactionID, int32 event, void* _journal) 39c1320b3aShyche { 40c1320b3aShyche TRACE("TRANSACTION WRITTEN id %i\n", transactionID); 41c1320b3aShyche } 42c1320b3aShyche 43c1320b3aShyche 44c1320b3aShyche status_t 45c1320b3aShyche Journal::_TransactionDone(bool success) 46c1320b3aShyche { 47c1320b3aShyche if (!success) { 48c1320b3aShyche cache_abort_transaction(fVolume->BlockCache(), fTransactionID); 49c1320b3aShyche return B_OK; 50c1320b3aShyche } 51c1320b3aShyche cache_end_transaction(fVolume->BlockCache(), fTransactionID, 52c1320b3aShyche &_TransactionWritten, this); 53c1320b3aShyche //cache_sync_transaction(fVolume->BlockCache(), fTransactionID); 54c1320b3aShyche return B_OK; 55c1320b3aShyche } 56c1320b3aShyche 57c1320b3aShyche 58c1320b3aShyche status_t 59c1320b3aShyche Journal::Lock(Transaction* owner) 60c1320b3aShyche { 61c1320b3aShyche status_t status = recursive_lock_lock(&fLock); 62c1320b3aShyche if (status != B_OK) 63c1320b3aShyche return status; 64c1320b3aShyche if (recursive_lock_get_recursion(&fLock) > 1) { 65c1320b3aShyche // we'll just use the current transaction again 66c1320b3aShyche return B_OK; 67c1320b3aShyche } 68c1320b3aShyche 69c1320b3aShyche 70c1320b3aShyche if (owner != NULL) 71c1320b3aShyche owner->SetParent(fOwner); 72c1320b3aShyche 73c1320b3aShyche fOwner = owner; 74c1320b3aShyche 75c1320b3aShyche if (fOwner != NULL) { 76c1320b3aShyche fTransactionID = cache_start_transaction(fVolume->BlockCache()); 77c1320b3aShyche 78c1320b3aShyche if (fTransactionID < B_OK) { 79c1320b3aShyche recursive_lock_unlock(&fLock); 80c1320b3aShyche return fTransactionID; 81c1320b3aShyche } 82c1320b3aShyche fCurrentGeneration++; 83c1320b3aShyche TRACE("Journal::Lock() start transaction id: %i\n", fTransactionID); 84c1320b3aShyche } 85c1320b3aShyche 86c1320b3aShyche return B_OK; 87c1320b3aShyche } 88c1320b3aShyche 89c1320b3aShyche 90c1320b3aShyche status_t 91c1320b3aShyche Journal::UnLock(Transaction* owner, bool success) 92c1320b3aShyche { 93c1320b3aShyche if (recursive_lock_get_recursion(&fLock) == 1) { 94c1320b3aShyche if (owner != NULL) { 95c1320b3aShyche status_t status = _TransactionDone(success); 96c1320b3aShyche if (status != B_OK) 97c1320b3aShyche return status; 98c1320b3aShyche fOwner = owner->Parent(); 99c1320b3aShyche } else { 100c1320b3aShyche fOwner = NULL; 101c1320b3aShyche } 102c1320b3aShyche } 103c1320b3aShyche recursive_lock_unlock(&fLock); 104c1320b3aShyche return B_OK; 105c1320b3aShyche } 106c1320b3aShyche 107c1320b3aShyche 108c1320b3aShyche // Transaction 109c1320b3aShyche 110c1320b3aShyche 111c1320b3aShyche Transaction::Transaction(Volume* volume) 112c1320b3aShyche : 113c1320b3aShyche fJournal(NULL), 114c1320b3aShyche fParent(NULL) 115c1320b3aShyche { 116c1320b3aShyche Start(volume); 117c1320b3aShyche } 118c1320b3aShyche 119c1320b3aShyche 120c1320b3aShyche Transaction::Transaction() 121c1320b3aShyche : 122c1320b3aShyche fJournal(NULL), 123c1320b3aShyche fParent(NULL) 124c1320b3aShyche { 125c1320b3aShyche } 126c1320b3aShyche 127c1320b3aShyche 128c1320b3aShyche Transaction::~Transaction() 129c1320b3aShyche { 130c1320b3aShyche if (fJournal != NULL) { 131c1320b3aShyche fJournal->UnLock(this, false); 132c1320b3aShyche } 133c1320b3aShyche } 134c1320b3aShyche 135c1320b3aShyche 136c1320b3aShyche bool 137c1320b3aShyche Transaction::HasBlock(fsblock_t blockNumber) const 138c1320b3aShyche { 139c1320b3aShyche return cache_has_block_in_transaction(fJournal->GetVolume()->BlockCache(), 140c1320b3aShyche ID(), blockNumber); 141c1320b3aShyche } 142c1320b3aShyche 143c1320b3aShyche 144c1320b3aShyche status_t 145c1320b3aShyche Transaction::Start(Volume* volume) 146c1320b3aShyche { 147c1320b3aShyche if (fJournal != NULL) 148c1320b3aShyche return B_OK; 149c1320b3aShyche 150c1320b3aShyche fJournal = volume->GetJournal(); 151c1320b3aShyche if (fJournal != NULL && fJournal->Lock(this) == B_OK) { 152c1320b3aShyche return B_OK; 153c1320b3aShyche } 154c1320b3aShyche fJournal = NULL; 155c1320b3aShyche return B_ERROR; 156c1320b3aShyche } 157c1320b3aShyche 158c1320b3aShyche 159c1320b3aShyche status_t 160c1320b3aShyche Transaction::Done() 161c1320b3aShyche { 162c1320b3aShyche status_t status = B_OK; 163c1320b3aShyche if (fJournal != NULL) { 164c1320b3aShyche status = fJournal->UnLock(this, true); 165c1320b3aShyche if (status == B_OK) 166c1320b3aShyche fJournal = NULL; 167c1320b3aShyche } 168c1320b3aShyche return status; 169c1320b3aShyche } 170