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