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