xref: /haiku/src/add-ons/kernel/file_systems/btrfs/Journal.cpp (revision f10ebdb1f74093594a5440651ca26be231a9bd2b)
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 
Journal(Volume * volume)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 
~Journal()31 Journal::~Journal()
32 {
33 	recursive_lock_destroy(&fLock);
34 }
35 
36 
37 /*static*/ void
_TransactionWritten(int32 transactionID,int32 event,void * _journal)38 Journal::_TransactionWritten(int32 transactionID, int32 event, void* _journal)
39 {
40 	TRACE("TRANSACTION WRITTEN id %i\n", transactionID);
41 }
42 
43 
44 status_t
_TransactionDone(bool success)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
Lock(Transaction * owner)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
UnLock(Transaction * owner,bool success)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 
Transaction(Volume * volume)111 Transaction::Transaction(Volume* volume)
112 	:
113 	fJournal(NULL),
114 	fParent(NULL)
115 {
116 	Start(volume);
117 }
118 
119 
Transaction()120 Transaction::Transaction()
121 	:
122 	fJournal(NULL),
123 	fParent(NULL)
124 {
125 }
126 
127 
~Transaction()128 Transaction::~Transaction()
129 {
130 	if (fJournal != NULL) {
131 		fJournal->UnLock(this, false);
132 	}
133 }
134 
135 
136 bool
HasBlock(fsblock_t blockNumber) const137 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
Start(Volume * volume)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
Done()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