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 20Journal::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 31Journal::~Journal() 32{ 33 recursive_lock_destroy(&fLock); 34} 35 36 37/*static*/ void 38Journal::_TransactionWritten(int32 transactionID, int32 event, void* _journal) 39{ 40 TRACE("TRANSACTION WRITTEN id %i\n", transactionID); 41} 42 43 44status_t 45Journal::_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 58status_t 59Journal::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 90status_t 91Journal::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 111Transaction::Transaction(Volume* volume) 112 : 113 fJournal(NULL), 114 fParent(NULL) 115{ 116 Start(volume); 117} 118 119 120Transaction::Transaction() 121 : 122 fJournal(NULL), 123 fParent(NULL) 124{ 125} 126 127 128Transaction::~Transaction() 129{ 130 if (fJournal != NULL) { 131 fJournal->UnLock(this, false); 132 } 133} 134 135 136bool 137Transaction::HasBlock(fsblock_t blockNumber) const 138{ 139 return cache_has_block_in_transaction(fJournal->GetVolume()->BlockCache(), 140 ID(), blockNumber); 141} 142 143 144status_t 145Transaction::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 159status_t 160Transaction::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