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