xref: /haiku/src/add-ons/kernel/file_systems/btrfs/Journal.cpp (revision c1320b3a33417a6702471014dac9d089c7036bc3)
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