xref: /haiku/src/tests/system/kernel/file_corruption/fs/Block.cpp (revision 4701667eb28ff895b6f2e4f1d83e668a4265721c)
1 /*
2  * Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "Block.h"
8 
9 #include <fs_cache.h>
10 
11 #include "Transaction.h"
12 #include "Volume.h"
13 
14 
15 void
TransferFrom(Block & other)16 Block::TransferFrom(Block& other)
17 {
18 	Put();
19 
20 	fVolume = other.fVolume;
21 	fData = other.fData;
22 	fIndex = other.fIndex;
23 	fTransaction = other.fTransaction;
24 
25 	other.fVolume = NULL;
26 	other.fData = NULL;
27 }
28 
29 
30 bool
GetReadable(Volume * volume,uint64 blockIndex)31 Block::GetReadable(Volume* volume, uint64 blockIndex)
32 {
33 	Put();
34 
35 	return _Init(volume, blockIndex,
36 		block_cache_get(volume->BlockCache(), blockIndex), NULL);
37 }
38 
39 
40 bool
GetWritable(Volume * volume,uint64 blockIndex,Transaction & transaction)41 Block::GetWritable(Volume* volume, uint64 blockIndex, Transaction& transaction)
42 {
43 	Put();
44 
45 	status_t error = transaction.RegisterBlock(blockIndex);
46 	if (error != B_OK)
47 		return false;
48 
49 	return _Init(volume, blockIndex,
50 		block_cache_get_writable(volume->BlockCache(), blockIndex,
51 			transaction.ID()),
52 		&transaction);
53 }
54 
55 
56 bool
GetZero(Volume * volume,uint64 blockIndex,Transaction & transaction)57 Block::GetZero(Volume* volume, uint64 blockIndex, Transaction& transaction)
58 {
59 	Put();
60 
61 	status_t error = transaction.RegisterBlock(blockIndex);
62 	if (error != B_OK)
63 		return false;
64 
65 	return _Init(volume, blockIndex,
66 		block_cache_get_empty(volume->BlockCache(), blockIndex,
67 			transaction.ID()),
68 		&transaction);
69 }
70 
71 
72 status_t
MakeWritable(Transaction & transaction)73 Block::MakeWritable(Transaction& transaction)
74 {
75 	if (fVolume == NULL)
76 		return B_BAD_VALUE;
77 	if (fTransaction != NULL)
78 		return B_OK;
79 
80 	status_t error = transaction.RegisterBlock(fIndex);
81 	if (error != B_OK)
82 		return error;
83 
84 	error = block_cache_make_writable(fVolume->BlockCache(), fIndex,
85 		transaction.ID());
86 	if (error != B_OK) {
87 		transaction.PutBlock(fIndex, NULL);
88 		return error;
89 	}
90 
91 	fTransaction = &transaction;
92 	return B_OK;
93 }
94 
95 
96 void
Put()97 Block::Put()
98 {
99 	if (fVolume != NULL) {
100 		if (fTransaction != NULL)
101 			fTransaction->PutBlock(fIndex, fData);
102 
103 		block_cache_put(fVolume->BlockCache(), fIndex);
104 		fVolume = NULL;
105 		fData = NULL;
106 	}
107 }
108 
109 
110 bool
_Init(Volume * volume,uint64 blockIndex,const void * data,Transaction * transaction)111 Block::_Init(Volume* volume, uint64 blockIndex, const void* data,
112 	Transaction* transaction)
113 {
114 	if (data == NULL)
115 		return false;
116 
117 	fVolume = volume;
118 	fData = const_cast<void*>(data);
119 	fIndex = blockIndex;
120 	fTransaction = transaction;
121 
122 	return true;
123 }
124