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