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