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