2 * Copyright 2007, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Copyright 2008-2012, Axel Dörfler, axeld@pinc-software.de.
5 * Distributed under the terms of the MIT License.
10 #include "InitializeParameterEditor.h"
14 #include <Directory.h>
19 #include <DiskDeviceTypes.h>
20 #include <MutablePartition.h>
22 #include <AutoDeleter.h>
23 #include <StringForSize.h>
30 #include "bfs_control.h"
31 #include "bfs_disk_system.h"
37 static const uint32 kDiskSystemFlags
=
39 // | B_DISK_SYSTEM_SUPPORTS_CHECKING
40 // | B_DISK_SYSTEM_SUPPORTS_REPAIRING
41 // | B_DISK_SYSTEM_SUPPORTS_RESIZING
42 // | B_DISK_SYSTEM_SUPPORTS_MOVING
43 // | B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_NAME
44 // | B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_PARAMETERS
45 | B_DISK_SYSTEM_SUPPORTS_INITIALIZING
46 | B_DISK_SYSTEM_SUPPORTS_CONTENT_NAME
47 // | B_DISK_SYSTEM_SUPPORTS_DEFRAGMENTING
48 // | B_DISK_SYSTEM_SUPPORTS_DEFRAGMENTING_WHILE_MOUNTED
49 | B_DISK_SYSTEM_SUPPORTS_CHECKING_WHILE_MOUNTED
50 | B_DISK_SYSTEM_SUPPORTS_REPAIRING_WHILE_MOUNTED
51 // | B_DISK_SYSTEM_SUPPORTS_RESIZING_WHILE_MOUNTED
52 // | B_DISK_SYSTEM_SUPPORTS_MOVING_WHILE_MOUNTED
53 // | B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_NAME_WHILE_MOUNTED
54 // | B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_PARAMETERS_WHILE_MOUNTED
59 size_string(double size
)
62 char* buffer
= string
.LockBuffer(256);
63 string_for_size(size
, buffer
, 256);
65 string
.UnlockBuffer();
70 // #pragma mark - BFSAddOn
74 : BDiskSystemAddOn(kPartitionTypeBFS
, kDiskSystemFlags
)
85 BFSAddOn::CreatePartitionHandle(BMutablePartition
* partition
,
86 BPartitionHandle
** _handle
)
88 BFSPartitionHandle
* handle
= new(nothrow
) BFSPartitionHandle(partition
);
92 status_t error
= handle
->Init();
104 BFSAddOn::CanInitialize(const BMutablePartition
* partition
)
106 // TODO: Check partition size.
112 BFSAddOn::ValidateInitialize(const BMutablePartition
* partition
, BString
* name
,
113 const char* parameterString
)
115 if (!CanInitialize(partition
) || !name
)
120 // truncate, if it is too long
121 if (name
->Length() >= BFS_DISK_NAME_LENGTH
)
122 name
->Truncate(BFS_DISK_NAME_LENGTH
- 1);
124 // replace '/' by '-'
125 name
->ReplaceAll('/', '-');
128 initialize_parameters parameters
;
129 status_t error
= parse_initialize_parameters(parameterString
, parameters
);
138 BFSAddOn::Initialize(BMutablePartition
* partition
, const char* name
,
139 const char* parameterString
, BPartitionHandle
** _handle
)
141 if (!CanInitialize(partition
) || check_volume_name(name
) != B_OK
)
144 initialize_parameters parameters
;
145 status_t error
= parse_initialize_parameters(parameterString
, parameters
);
150 BFSPartitionHandle
* handle
= new(nothrow
) BFSPartitionHandle(partition
);
153 ObjectDeleter
<BFSPartitionHandle
> handleDeleter(handle
);
155 // init the partition
156 error
= partition
->SetContentType(Name());
159 // TODO: The content type could as well be set by the caller.
161 partition
->SetContentName(name
);
162 partition
->SetContentParameters(parameterString
);
163 uint32 blockSize
= parameters
.blockSize
;
164 partition
->SetBlockSize(blockSize
);
165 partition
->SetContentSize(partition
->Size() / blockSize
* blockSize
);
166 partition
->Changed(B_PARTITION_CHANGED_INITIALIZATION
);
168 *_handle
= handleDeleter
.Detach();
175 BFSAddOn::GetParameterEditor(B_PARAMETER_EDITOR_TYPE type
,
176 BPartitionParameterEditor
** editor
)
179 if (type
== B_INITIALIZE_PARAMETER_EDITOR
) {
181 *editor
= new InitializeBFSEditor();
182 } catch (std::bad_alloc
) {
187 return B_NOT_SUPPORTED
;
191 // #pragma mark - BFSPartitionHandle
194 BFSPartitionHandle::BFSPartitionHandle(BMutablePartition
* partition
)
195 : BPartitionHandle(partition
)
200 BFSPartitionHandle::~BFSPartitionHandle()
206 BFSPartitionHandle::Init()
208 // TODO: Check parameters.
214 BFSPartitionHandle::SupportedOperations(uint32 mask
)
216 return kDiskSystemFlags
& mask
;
221 BFSPartitionHandle::Repair(bool checkOnly
)
223 BVolume
volume(Partition()->VolumeID());
224 BDirectory directory
;
225 volume
.GetRootDirectory(&directory
);
227 path
.SetTo(&directory
, ".");
229 int fd
= open(path
.Path(), O_RDONLY
);
233 FileDescriptorCloser
closer(fd
);
235 struct check_control result
;
236 memset(&result
, 0, sizeof(result
));
237 result
.magic
= BFS_IOCTL_CHECK_MAGIC
;
240 //printf("will fix any severe errors!\n");
241 result
.flags
|= BFS_FIX_BITMAP_ERRORS
| BFS_REMOVE_WRONG_TYPES
242 | BFS_REMOVE_INVALID
| BFS_FIX_NAME_MISMATCHES
| BFS_FIX_BPLUSTREES
;
246 if (ioctl(fd
, BFS_IOCTL_START_CHECKING
, &result
, sizeof(result
)) < 0)
249 uint64 attributeDirectories
= 0, attributes
= 0;
250 uint64 files
= 0, directories
= 0, indices
= 0;
252 uint32 previousPass
= result
.pass
;
254 // check all files and report errors
255 while (ioctl(fd
, BFS_IOCTL_CHECK_NEXT_NODE
, &result
,
256 sizeof(result
)) == 0) {
257 if (++counter
% 50 == 0)
258 printf("%9" B_PRId64
" nodes processed\x1b[1A\n", counter
);
260 if (result
.pass
== BFS_CHECK_PASS_BITMAP
) {
262 printf("%s (inode = %" B_PRIdINO
")", result
.name
, result
.inode
);
263 if ((result
.errors
& BFS_MISSING_BLOCKS
) != 0)
264 printf(", some blocks weren't allocated");
265 if ((result
.errors
& BFS_BLOCKS_ALREADY_SET
) != 0)
266 printf(", has blocks already set");
267 if ((result
.errors
& BFS_INVALID_BLOCK_RUN
) != 0)
268 printf(", has invalid block run(s)");
269 if ((result
.errors
& BFS_COULD_NOT_OPEN
) != 0)
270 printf(", could not be opened");
271 if ((result
.errors
& BFS_WRONG_TYPE
) != 0)
272 printf(", has wrong type");
273 if ((result
.errors
& BFS_NAMES_DONT_MATCH
) != 0)
274 printf(", names don't match");
275 if ((result
.errors
& BFS_INVALID_BPLUSTREE
) != 0)
276 printf(", invalid b+tree");
280 if ((result
.mode
& (S_INDEX_DIR
| 0777)) == S_INDEX_DIR
)
282 else if (result
.mode
& S_ATTR_DIR
)
283 attributeDirectories
++;
284 else if (result
.mode
& S_ATTR
)
286 else if (S_ISDIR(result
.mode
))
290 } else if (result
.pass
== BFS_CHECK_PASS_INDEX
) {
291 if (previousPass
!= result
.pass
) {
292 printf("Recreating broken index b+trees...\n");
293 previousPass
= result
.pass
;
300 if (ioctl(fd
, BFS_IOCTL_STOP_CHECKING
, &result
, sizeof(result
)) != 0)
303 printf(" %" B_PRIu64
" nodes checked,\n\t%" B_PRIu64
" blocks not "
304 "allocated,\n\t%" B_PRIu64
" blocks already set,\n\t%" B_PRIu64
305 " blocks could be freed\n\n", counter
, result
.stats
.missing
,
306 result
.stats
.already_set
, result
.stats
.freed
);
307 printf("\tfiles\t\t%" B_PRIu64
"\n\tdirectories\t%" B_PRIu64
"\n"
308 "\tattributes\t%" B_PRIu64
"\n\tattr. dirs\t%" B_PRIu64
"\n"
309 "\tindices\t\t%" B_PRIu64
"\n", files
, directories
, attributes
,
310 attributeDirectories
, indices
);
312 printf("\n\tdirect block runs\t\t%" B_PRIu64
" (%s)\n",
313 result
.stats
.direct_block_runs
, size_string(1.0
314 * result
.stats
.blocks_in_direct
315 * result
.stats
.block_size
).String());
316 printf("\tindirect block runs\t\t%" B_PRIu64
" (in %" B_PRIu64
317 " array blocks, %s)\n", result
.stats
.indirect_block_runs
,
318 result
.stats
.indirect_array_blocks
,
319 size_string(1.0 * result
.stats
.blocks_in_indirect
320 * result
.stats
.block_size
).String());
321 printf("\tdouble indirect block runs\t%" B_PRIu64
" (in %" B_PRIu64
322 " array blocks, %s)\n", result
.stats
.double_indirect_block_runs
,
323 result
.stats
.double_indirect_array_blocks
,
324 size_string(1.0 * result
.stats
.blocks_in_double_indirect
325 * result
.stats
.block_size
).String());
326 // TODO: this is currently not maintained correctly
327 //printf("\tpartial block runs\t%" B_PRIu64 "\n",
328 // result.stats.partial_block_runs);
330 if (result
.status
== B_ENTRY_NOT_FOUND
)
331 result
.status
= B_OK
;
333 return result
.status
;
341 get_disk_system_add_ons(BList
* addOns
)
343 BFSAddOn
* addOn
= new(nothrow
) BFSAddOn
;
347 if (!addOns
->AddItem(addOn
)) {