1 /*
2 core.c -- reiserfs general code
3 Copyright (C) 2001, 2002 Yury Umanets <torque@ukrpost.net>, see COPYING for
4 licensing and copyright details.
5 */
6
7 #ifdef HAVE_CONFIG_H
8 # include <config.h>
9 #endif
10
11 #include <stdlib.h>
12 #include <string.h>
13 #include <fcntl.h>
14
15 #include <reiserfs/reiserfs.h>
16 #include <reiserfs/debug.h>
17 #include <reiserfs/callback.h>
18
19 #define N_(String) (String)
20 #if ENABLE_NLS
21 # include <libintl.h>
22 # define _(String) dgettext (PACKAGE, String)
23 #else
24 # define _(String) (String)
25 #endif
26
27 #define reiserfs_fs_bitmap_check_state(fs, action) \
28 do { \
29 if (!reiserfs_fs_bitmap_opened(fs)) { \
30 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL, \
31 _("Bitmap isn't opened. Possible filesystem was opened in "\
32 "the \"fast\" maner.")); \
33 action; \
34 } \
35 } while (0)
36
37 /* Journal functions */
reiserfs_fs_journal_opened(reiserfs_fs_t * fs)38 int reiserfs_fs_journal_opened(reiserfs_fs_t *fs) {
39 ASSERT(fs != NULL, return 0);
40 return fs->journal ? 1 : 0;
41 }
42
reiserfs_fs_journal_size(reiserfs_fs_t * fs)43 blk_t reiserfs_fs_journal_size(reiserfs_fs_t *fs) {
44 ASSERT(fs != NULL, return 0);
45 return get_jp_len(get_sb_jp(fs->super));
46 }
47
reiserfs_fs_journal_offset(reiserfs_fs_t * fs)48 blk_t reiserfs_fs_journal_offset(reiserfs_fs_t *fs) {
49 ASSERT(fs != NULL, return 0);
50 return get_jp_start(get_sb_jp(fs->super));
51 }
52
reiserfs_fs_journal_trans_max(reiserfs_fs_t * fs)53 blk_t reiserfs_fs_journal_trans_max(reiserfs_fs_t *fs) {
54 ASSERT(fs != NULL, return 0);
55 return get_jp_max_trans_len(get_sb_jp(fs->super));
56 }
57
reiserfs_fs_journal_area(reiserfs_fs_t * fs)58 blk_t reiserfs_fs_journal_area(reiserfs_fs_t *fs) {
59 ASSERT(fs != NULL, return 0);
60 return (reiserfs_fs_journal_relocated(fs) ?
61 get_sb_reserved_for_journal(fs->super) :
62 get_jp_len(get_sb_jp(fs->super)) + 1);
63 }
64
65 static char *journal_kinds[] = {"standard", "relocated"};
66
reiserfs_fs_journal_kind_str(int relocated)67 const char *reiserfs_fs_journal_kind_str(int relocated) {
68 if (relocated < 0 || relocated > 1)
69 return NULL;
70
71 return journal_kinds[relocated];
72 }
73
reiserfs_fs_journal_kind(reiserfs_fs_t * fs)74 int reiserfs_fs_journal_kind(reiserfs_fs_t *fs) {
75 ASSERT(fs != NULL, return 0);
76 return reiserfs_tools_journal_signature(fs->super->s_v1.sb_magic);
77 }
78
reiserfs_fs_super_magic_update(reiserfs_super_t * super,int format,int relocated)79 static void reiserfs_fs_super_magic_update(reiserfs_super_t *super, int format,
80 int relocated)
81 {
82 if (!relocated) {
83 switch (format) {
84 case FS_FORMAT_3_5: {
85 memcpy(super->s_v1.sb_magic, REISERFS_3_5_SUPER_SIGNATURE,
86 sizeof (REISERFS_3_5_SUPER_SIGNATURE));
87 break;
88 }
89 case FS_FORMAT_3_6: {
90 memcpy(super->s_v1.sb_magic, REISERFS_3_6_SUPER_SIGNATURE,
91 sizeof (REISERFS_3_6_SUPER_SIGNATURE));
92 break;
93 }
94 }
95 } else {
96 memcpy(super->s_v1.sb_magic, REISERFS_JR_SUPER_SIGNATURE,
97 sizeof (REISERFS_JR_SUPER_SIGNATURE));
98 }
99 }
100
reiserfs_fs_journal_tune_check(reiserfs_fs_t * fs,dal_t * dal,blk_t start,blk_t len,blk_t max_trans,int relocated)101 static int reiserfs_fs_journal_tune_check(reiserfs_fs_t *fs, dal_t *dal,
102 blk_t start, blk_t len, blk_t max_trans, int relocated)
103 {
104 reiserfs_journal_trans_t old_trans, new_trans;
105
106 ASSERT(fs != NULL, return 0);
107 ASSERT(dal != NULL, return 0);
108
109 if (!relocated && relocated == reiserfs_fs_journal_relocated(fs)) {
110 if (start != get_jp_start(get_sb_jp(fs->super))) {
111 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
112 _("Can't change start of the standard journal."));
113 return 0;
114 }
115 }
116
117 /* Checking for non-replayed transactions */
118 memset(&old_trans, 0, sizeof(old_trans));
119 memset(&new_trans, 0, sizeof(new_trans));
120
121 if (reiserfs_journal_boundary_transactions(fs->journal, &old_trans,
122 &new_trans))
123 {
124 if (new_trans.jt_trans_id != get_jh_last_flushed(&fs->journal->head)) {
125 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
126 _("There are non-replayed transaction in old journal,"
127 " check filesystem consistency first."));
128 return 0;
129 }
130 }
131
132 return 1;
133 }
134
reiserfs_fs_journal_switch_to_standard(reiserfs_fs_t * fs,dal_t * dal,blk_t max_trans)135 static int reiserfs_fs_journal_switch_to_standard(reiserfs_fs_t *fs, dal_t *dal,
136 blk_t max_trans)
137 {
138 reiserfs_gauge_t *gauge;
139 blk_t root_blk, new_len, max_len;
140 reiserfs_segment_t src_segment, dst_segment;
141
142 if (!get_sb_reserved_for_journal(fs->super)) {
143 new_len = get_jp_len(get_sb_jp(fs->super));
144
145 if (new_len >= reiserfs_fs_free_size(fs))
146 new_len = reiserfs_fs_free_size(fs) - 1;
147
148 /* Checking whether old relocated journal has valid size */
149 max_len = reiserfs_journal_max_len(fs->dal, fs->super_off + 2, 0);
150
151 if (new_len > max_len)
152 new_len = max_len;
153
154 if (new_len < JOURNAL_MIN_SIZE)
155 new_len = JOURNAL_MIN_SIZE;
156
157 if (new_len >= reiserfs_fs_free_size(fs)) {
158 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
159 _("Not enought free space on host device for %lu blocks "
160 "of journal."), new_len);
161 return 0;
162 }
163
164 /* Relocation of the all occupied blocks */
165 if (!reiserfs_segment_init(&src_segment, fs->dal, fs->super_off + 2,
166 fs->super_off + 2 + new_len))
167 return 0;
168
169 if (!reiserfs_segment_init(&dst_segment, fs->dal, fs->super_off + 2 +
170 new_len + 1, reiserfs_fs_size(fs)))
171 return 0;
172
173 if (!reiserfs_fs_state_update(fs, FS_CORRUPTED))
174 return 0;
175
176 if ((gauge = libreiserfs_get_gauge())) {
177 libreiserfs_gauge_reset(gauge);
178 libreiserfs_gauge_set_name(gauge, _("relocating occupied area"));
179 }
180
181 if (!(root_blk = reiserfs_segment_relocate(fs, &dst_segment,
182 fs, &src_segment, 0)))
183 return 0;
184
185 if (gauge)
186 libreiserfs_gauge_finish(gauge, 1);
187
188 /* Updating root block */
189 set_sb_root_block(fs->super, root_blk);
190 } else
191 new_len = get_sb_reserved_for_journal(fs->super) - 1;
192
193 reiserfs_fs_journal_close(fs);
194
195 /* Creating new journal on host device */
196 if (!reiserfs_fs_journal_create(fs, fs->dal, fs->super_off + 2, new_len, max_trans))
197 return 0;
198
199 /* Updating free blocks */
200 if (!get_sb_reserved_for_journal(fs->super))
201 set_sb_free_blocks(fs->super, get_sb_free_blocks(fs->super) - (new_len + 1));
202
203 /* Updating super signature and reserved for journal field */
204 reiserfs_fs_super_magic_update(fs->super, get_sb_format(fs->super),
205 !dal_equals(fs->dal, fs->journal->dal));
206
207 set_sb_reserved_for_journal(fs->super, 0);
208
209 if (!reiserfs_fs_state_update(fs, FS_CONSISTENT))
210 return 0;
211
212 return 1;
213 }
214
reiserfs_fs_journal_switch_to_relocated(reiserfs_fs_t * fs,dal_t * dal,blk_t start,blk_t len,blk_t max_trans)215 static int reiserfs_fs_journal_switch_to_relocated(reiserfs_fs_t *fs, dal_t *dal,
216 blk_t start, blk_t len, blk_t max_trans)
217 {
218 blk_t old_len;
219
220 /* Updating journal */
221 reiserfs_fs_journal_close(fs);
222
223 old_len = get_jp_len(get_sb_jp(fs->super));
224
225 /* Creating new journal */
226 if (!reiserfs_fs_journal_create(fs, dal, start, len, max_trans))
227 return 0;
228
229 /* Updating reserved_for_journal field to old journal size */
230 reiserfs_fs_super_magic_update(fs->super, get_sb_format(fs->super),
231 !dal_equals(fs->dal, fs->journal->dal));
232
233 set_sb_reserved_for_journal(fs->super, old_len + 1);
234
235 return 1;
236 }
237
reiserfs_fs_journal_tune(reiserfs_fs_t * fs,dal_t * dal,blk_t start,blk_t len,blk_t max_trans)238 int reiserfs_fs_journal_tune(reiserfs_fs_t *fs, dal_t *dal,
239 blk_t start, blk_t len, blk_t max_trans)
240 {
241 int relocated;
242
243 ASSERT(fs != NULL, return 0);
244 ASSERT(dal != NULL, return 0);
245
246 reiserfs_fs_bitmap_check_state(fs, return 0);
247
248 if (!reiserfs_fs_journal_opened(fs))
249 return 0;
250
251 relocated = !dal_equals(fs->dal, dal);
252
253 if (!reiserfs_journal_params_check(dal, start, len, relocated))
254 return 0;
255
256 if (!reiserfs_fs_journal_tune_check(fs, dal, start, len,
257 max_trans, relocated))
258 return 0;
259
260 if (!reiserfs_fs_state_update(fs, FS_CORRUPTED))
261 return 0;
262
263 if (relocated != reiserfs_fs_journal_relocated(fs)) {
264 if (!relocated) {
265 if (!reiserfs_fs_journal_switch_to_standard(fs, dal,
266 max_trans))
267 return 0;
268 } else {
269 if (!reiserfs_fs_journal_switch_to_relocated(fs, dal,
270 start, len, max_trans))
271 return 0;
272 }
273 } else {
274 /*
275 If new journal is relocated and boundaries changed, then we need
276 to fill new area by zero
277 */
278 if (relocated && (start != get_jp_start(get_sb_jp(fs->super)) ||
279 len != get_jp_len(get_sb_jp(fs->super))))
280 {
281 reiserfs_fs_journal_close(fs);
282
283 /* Creating new journal */
284 if (!reiserfs_fs_journal_create(fs, dal, start, len, max_trans))
285 return 0;
286 }
287
288 if (!relocated && start == get_jp_start(get_sb_jp(fs->super)) &&
289 len == get_jp_len(get_sb_jp(fs->super)))
290 {
291 /* Journal location and boundaries are still unchnaged */
292 reiserfs_journal_params_update(&fs->journal->head.jh_params, start, len,
293 max_trans, get_jp_dev(get_sb_jp(fs->super)),
294 get_sb_block_size(fs->super));
295
296 memcpy(get_sb_jp(fs->super), &fs->journal->head.jh_params,
297 sizeof(fs->journal->head.jh_params));
298 }
299 }
300
301 if (!reiserfs_fs_state_update(fs, FS_CONSISTENT))
302 return 0;
303
304 reiserfs_fs_mark_super_dirty(fs);
305 reiserfs_fs_mark_bitmap_dirty(fs);
306 reiserfs_fs_mark_journal_dirty(fs);
307
308 return 1;
309 }
310
reiserfs_fs_journal_open(reiserfs_fs_t * fs,dal_t * dal)311 int reiserfs_fs_journal_open(reiserfs_fs_t *fs, dal_t *dal) {
312 blk_t start;
313 int relocated;
314
315 ASSERT(fs != NULL, return 0);
316
317 if (reiserfs_fs_journal_opened(fs)) {
318 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
319 _("Journal already opened."));
320 return 0;
321 }
322
323 start = get_jp_start(get_sb_jp(fs->super));
324 relocated = dal && !dal_equals(fs->dal, dal);
325
326 if (relocated != reiserfs_fs_journal_relocated(fs)) {
327 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
328 _("Journal kind mismatch has detected. Filesystem has %s journal, but "
329 "specified %s journal."),
330 reiserfs_fs_journal_kind_str(reiserfs_fs_journal_relocated(fs)),
331 reiserfs_fs_journal_kind_str(relocated));
332 return 0;
333 }
334
335 if (!(fs->journal = reiserfs_journal_open(dal, start,
336 get_jp_len(get_sb_jp(fs->super)), relocated)))
337 {
338 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
339 _("Couldn't open journal."));
340 return 0;
341 }
342
343 reiserfs_fs_mark_journal_clean(fs);
344
345 return 1;
346 }
347
reiserfs_fs_journal_reopen(reiserfs_fs_t * fs,dal_t * dal)348 int reiserfs_fs_journal_reopen(reiserfs_fs_t *fs, dal_t *dal) {
349
350 ASSERT(fs != NULL, return 0);
351 ASSERT(dal != NULL, return 0);
352
353 if (reiserfs_fs_journal_opened(fs))
354 reiserfs_fs_journal_close(fs);
355
356 return reiserfs_fs_journal_open(fs, dal);
357 }
358
reiserfs_fs_journal_create(reiserfs_fs_t * fs,dal_t * dal,blk_t start,blk_t len,blk_t max_trans)359 int reiserfs_fs_journal_create(reiserfs_fs_t *fs, dal_t *dal, blk_t start,
360 blk_t len, blk_t max_trans)
361 {
362 int relocated;
363
364 ASSERT(fs != NULL, return 0);
365
366 if (reiserfs_fs_journal_opened(fs)) {
367 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
368 _("Journal already opened."));
369 return 0;
370 }
371
372 reiserfs_fs_bitmap_check_state(fs, return 0);
373 relocated = dal && !dal_equals(fs->dal, dal);
374
375 start = (relocated ? start : fs->super_off + 2);
376
377 if (!(fs->journal = reiserfs_journal_create(dal ? dal : fs->dal, start, len,
378 max_trans, relocated)))
379 {
380 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
381 _("Couldn't create journal."));
382 return 0;
383 }
384
385 /* Updating super's journal parameters */
386 memcpy(get_sb_jp(fs->super), &fs->journal->head.jh_params,
387 sizeof(fs->journal->head.jh_params));
388
389 /* Marking journal blocks as used. */
390 if (!relocated) {
391 blk_t blk;
392
393 /* Marking len and journal parameters block. */
394 for (blk = start; blk < start + len + 1; blk++)
395 reiserfs_fs_bitmap_use_block(fs, blk);
396 }
397
398 reiserfs_fs_mark_journal_clean(fs);
399 return 1;
400 }
401
reiserfs_fs_journal_recreate(reiserfs_fs_t * fs,dal_t * dal,blk_t start,blk_t len,blk_t max_trans)402 int reiserfs_fs_journal_recreate(reiserfs_fs_t *fs, dal_t *dal,
403 blk_t start, blk_t len, blk_t max_trans)
404 {
405 ASSERT(fs != NULL, return 0);
406
407 reiserfs_fs_bitmap_check_state(fs, return 0);
408
409 reiserfs_fs_journal_close(fs);
410 return reiserfs_fs_journal_create(fs, dal, start, len, max_trans);
411 }
412
reiserfs_fs_journal_sync(reiserfs_fs_t * fs)413 int reiserfs_fs_journal_sync(reiserfs_fs_t *fs) {
414
415 ASSERT(fs != NULL, return 0);
416
417 reiserfs_fs_bitmap_check_state(fs, return 0);
418
419 if (!reiserfs_fs_journal_opened(fs)) {
420 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
421 _("Journal isn't opened."));
422 return 0;
423 }
424
425 if (!reiserfs_journal_sync(fs->journal))
426 return 0;
427
428 reiserfs_fs_mark_journal_clean(fs);
429
430 return 1;
431 }
432
reiserfs_fs_journal_close(reiserfs_fs_t * fs)433 void reiserfs_fs_journal_close(reiserfs_fs_t *fs) {
434 ASSERT(fs != NULL, return);
435
436 if (!reiserfs_fs_journal_opened(fs)) {
437 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
438 _("Journal isn't opened."));
439 return;
440 }
441
442 reiserfs_journal_close(fs->journal);
443 fs->journal = NULL;
444 }
445
reiserfs_fs_journal(reiserfs_fs_t * fs)446 reiserfs_journal_t *reiserfs_fs_journal(reiserfs_fs_t *fs) {
447 ASSERT(fs != NULL, return NULL);
448 return fs->journal;
449 }
450
451 /* Bitmap functions */
reiserfs_fs_bitmap_opened(reiserfs_fs_t * fs)452 int reiserfs_fs_bitmap_opened(reiserfs_fs_t *fs) {
453 ASSERT(fs != NULL, return 0);
454 return fs->bitmap ? 1 : 0;
455 }
456
reiserfs_fs_bitmap_use_block(reiserfs_fs_t * fs,blk_t block)457 void reiserfs_fs_bitmap_use_block(reiserfs_fs_t *fs, blk_t block) {
458 ASSERT(fs != NULL, return);
459
460 reiserfs_fs_bitmap_check_state(fs, return);
461
462 reiserfs_bitmap_use_block(fs->bitmap, block);
463 reiserfs_fs_mark_bitmap_dirty(fs);
464 }
465
reiserfs_fs_bitmap_unuse_block(reiserfs_fs_t * fs,blk_t block)466 void reiserfs_fs_bitmap_unuse_block(reiserfs_fs_t *fs, blk_t block) {
467
468 ASSERT(fs != NULL, return);
469
470 reiserfs_fs_bitmap_check_state(fs, return);
471
472 reiserfs_bitmap_unuse_block(fs->bitmap, block);
473 reiserfs_fs_mark_bitmap_dirty(fs);
474 }
475
reiserfs_fs_bitmap_test_block(reiserfs_fs_t * fs,blk_t block)476 int reiserfs_fs_bitmap_test_block(reiserfs_fs_t *fs, blk_t block) {
477
478 ASSERT(fs != NULL, return 0);
479
480 reiserfs_fs_bitmap_check_state(fs, return 0);
481 return reiserfs_bitmap_test_block(fs->bitmap, block);
482 }
483
reiserfs_fs_bitmap_find_free_block(reiserfs_fs_t * fs,blk_t start)484 blk_t reiserfs_fs_bitmap_find_free_block(reiserfs_fs_t *fs,
485 blk_t start)
486 {
487 ASSERT(fs != NULL, return 0);
488
489 reiserfs_fs_bitmap_check_state(fs, return 0);
490 return reiserfs_bitmap_find_free(fs->bitmap, start);
491 }
492
reiserfs_fs_bitmap_calc_used(reiserfs_fs_t * fs)493 blk_t reiserfs_fs_bitmap_calc_used(reiserfs_fs_t *fs) {
494 ASSERT(fs != NULL, return 0);
495
496 reiserfs_fs_bitmap_check_state(fs, return 0);
497 return reiserfs_bitmap_calc_used(fs->bitmap);
498 }
499
reiserfs_fs_bitmap_calc_unused(reiserfs_fs_t * fs)500 blk_t reiserfs_fs_bitmap_calc_unused(reiserfs_fs_t *fs) {
501 ASSERT(fs != NULL, return 0);
502
503 reiserfs_fs_bitmap_check_state(fs, return 0);
504 return reiserfs_bitmap_calc_unused(fs->bitmap);
505 }
506
reiserfs_fs_bitmap_used(reiserfs_fs_t * fs)507 blk_t reiserfs_fs_bitmap_used(reiserfs_fs_t *fs) {
508 ASSERT(fs != NULL, return 0);
509
510 reiserfs_fs_bitmap_check_state(fs, return 0);
511 return reiserfs_bitmap_used(fs->bitmap);
512 }
513
reiserfs_fs_bitmap_unused(reiserfs_fs_t * fs)514 blk_t reiserfs_fs_bitmap_unused(reiserfs_fs_t *fs) {
515 ASSERT(fs != NULL, return 0);
516
517 reiserfs_fs_bitmap_check_state(fs, return 0);
518 return reiserfs_bitmap_unused(fs->bitmap);
519 }
520
reiserfs_fs_bitmap_check(reiserfs_fs_t * fs)521 int reiserfs_fs_bitmap_check(reiserfs_fs_t *fs) {
522 ASSERT(fs != NULL, return 0);
523
524 reiserfs_fs_bitmap_check_state(fs, return 0);
525 return reiserfs_bitmap_check(fs->bitmap);
526 }
527
reiserfs_fs_bitmap_open(reiserfs_fs_t * fs)528 int reiserfs_fs_bitmap_open(reiserfs_fs_t *fs) {
529
530 ASSERT(fs != NULL, return 0);
531
532 if (reiserfs_fs_bitmap_opened(fs)) {
533 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
534 _("Bitmap already opened."));
535 return 0;
536 }
537
538 if (!(fs->bitmap = reiserfs_bitmap_open(fs, fs->super_off + 1,
539 get_sb_block_count(fs->super)))) {
540 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
541 _("Couldn't open bitmap."));
542 return 0;
543 }
544
545 reiserfs_fs_mark_bitmap_clean(fs);
546 return 1;
547 }
548
reiserfs_fs_bitmap_create(reiserfs_fs_t * fs,size_t blocksize,blk_t fs_len)549 int reiserfs_fs_bitmap_create(reiserfs_fs_t *fs, size_t blocksize, blk_t fs_len) {
550
551 ASSERT(fs != NULL, return 0);
552
553 if (reiserfs_fs_bitmap_opened(fs)) {
554 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
555 _("Bitmap already opened."));
556 return 0;
557 }
558
559 if (!(fs->bitmap = reiserfs_bitmap_create(fs, (DEFAULT_SUPER_OFFSET / blocksize) + 1,
560 fs_len)))
561 {
562 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
563 _("Couldn't create bitmap."));
564 return 0;
565 }
566
567 reiserfs_fs_mark_bitmap_clean(fs);
568 return 1;
569 }
570
reiserfs_fs_bitmap_mark(reiserfs_fs_t * fs,reiserfs_segment_t * segment,int mark)571 static void reiserfs_fs_bitmap_mark(reiserfs_fs_t *fs, reiserfs_segment_t *segment, int mark) {
572 blk_t i;
573
574 for (i = 0; i < reiserfs_segment_len(segment); i++) {
575 mark ? reiserfs_fs_bitmap_use_block(fs, segment->start + i) :
576 reiserfs_fs_bitmap_unuse_block(fs, segment->start + i);
577 }
578 }
579
reiserfs_fs_bitmap_resize(reiserfs_fs_t * fs,long start,long end)580 int reiserfs_fs_bitmap_resize(reiserfs_fs_t *fs, long start, long end) {
581
582 ASSERT(fs != NULL, return 0);
583
584 reiserfs_fs_bitmap_check_state(fs, return 0);
585
586 if (!reiserfs_bitmap_resize(fs->bitmap, start, end)) {
587 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
588 _("Couldn't resize bitmap to (%lu - %lu) blocks."), start, end);
589 return 0;
590 }
591
592 reiserfs_fs_mark_bitmap_dirty(fs);
593
594 return 1;
595 }
596
reiserfs_fs_bitmap_sync(reiserfs_fs_t * fs)597 int reiserfs_fs_bitmap_sync(reiserfs_fs_t *fs) {
598
599 ASSERT(fs != NULL, return 0);
600
601 reiserfs_fs_bitmap_check_state(fs, return 0);
602
603 if (!reiserfs_bitmap_sync(fs->bitmap))
604 return 0;
605
606 reiserfs_fs_mark_bitmap_clean(fs);
607
608 return 1;
609 }
610
reiserfs_fs_bitmap_close(reiserfs_fs_t * fs)611 void reiserfs_fs_bitmap_close(reiserfs_fs_t *fs) {
612
613 ASSERT(fs != NULL, return);
614
615 reiserfs_fs_bitmap_check_state(fs, return);
616 reiserfs_bitmap_close(fs->bitmap);
617 fs->bitmap = NULL;
618 }
619
reiserfs_fs_bitmap_reopen(reiserfs_fs_t * fs)620 int reiserfs_fs_bitmap_reopen(reiserfs_fs_t *fs) {
621 ASSERT(fs != NULL, return 0);
622 reiserfs_fs_bitmap_close(fs);
623 return reiserfs_fs_bitmap_open(fs);
624 }
625
reiserfs_fs_bitmap(reiserfs_fs_t * fs)626 reiserfs_bitmap_t *reiserfs_fs_bitmap(reiserfs_fs_t *fs) {
627 ASSERT(fs != NULL, return NULL);
628 return fs->bitmap;
629 }
630
631 /* Superblock functions */
reiserfs_fs_super_sync(reiserfs_fs_t * fs)632 int reiserfs_fs_super_sync(reiserfs_fs_t *fs) {
633 reiserfs_block_t *block;
634
635 ASSERT(fs != NULL, return 0);
636 ASSERT(fs->dal != NULL, return 0);
637
638 if (!(block = reiserfs_block_alloc_with_copy(fs->dal, fs->super_off,
639 fs->super)))
640 goto error;
641
642 if (!reiserfs_block_write(fs->dal, block)) {
643 reiserfs_block_writing_failed(fs->super_off,
644 dal_error(fs->dal), goto error_free_block);
645 }
646
647 reiserfs_block_free(block);
648
649 reiserfs_fs_mark_super_clean(fs);
650 return 1;
651
652 error_free_block:
653 reiserfs_block_free(block);
654 error:
655 return 0;
656 }
657
reiserfs_fs_super_open_check(reiserfs_super_t * sb,blk_t dev_len,int quiet)658 static int reiserfs_fs_super_open_check(reiserfs_super_t *sb, blk_t dev_len, int quiet) {
659 int is_journal_dev, is_journal_magic;
660
661 ASSERT(sb != NULL, return 0);
662 ASSERT(dev_len > 0, return 0);
663
664 is_journal_dev = (get_jp_dev(get_sb_jp(sb)) ? 1 : 0);
665 is_journal_magic = reiserfs_tools_journal_signature(sb->s_v1.sb_magic);
666
667 if (is_journal_dev != is_journal_magic && !quiet) {
668 libreiserfs_exception_throw(EXCEPTION_WARNING, EXCEPTION_IGNORE,
669 _("Journal relocation flags mismatch. Journal device: %x, magic: %s."),
670 get_jp_dev(get_sb_jp(sb)), sb->s_v1.sb_magic);
671 }
672
673 if (get_sb_block_count(sb) > dev_len) {
674 if (!quiet) {
675 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
676 _("Superblock has an invalid block count %lu for device "
677 "length %lu blocks."), get_sb_block_count(sb), dev_len);
678 }
679 return 0;
680 }
681
682 return 1;
683 }
684
reiserfs_fs_super_probe(dal_t * dal,int quiet)685 static reiserfs_block_t *reiserfs_fs_super_probe(dal_t *dal, int quiet) {
686 reiserfs_super_t *super;
687 reiserfs_block_t *block;
688 int i, super_offset[] = {16, 2, -1};
689
690 ASSERT(dal != NULL, return NULL);
691
692 for (i = 0; super_offset[i] != -1; i++) {
693 if (!(block = reiserfs_block_read(dal, super_offset[i])) && !quiet ) {
694 libreiserfs_exception_throw(EXCEPTION_WARNING, EXCEPTION_IGNORE,
695 _("Reading block %lu for blocksize %d failed. %s."), super_offset[i],
696 dal_get_blocksize(dal), dal_error(dal));
697 } else {
698 super = (reiserfs_super_t *)block->data;
699
700 if (reiserfs_tools_any_signature((const char *)super->s_v1.sb_magic)) {
701 /*
702 Making some checks to make sure super block looks
703 correctly.
704 */
705 if (!dal_set_blocksize(dal, get_sb_block_size(super)) && !quiet) {
706 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
707 _("Invalid blocksize %d. It must power of two."),
708 get_sb_block_size(super));
709 reiserfs_block_free(block);
710 continue;
711 }
712
713 if (!reiserfs_fs_super_open_check(super, dal_len(dal), quiet)) {
714 reiserfs_block_free(block);
715 continue;
716 }
717 return block;
718 }
719 reiserfs_block_free(block);
720 }
721 }
722
723 return NULL;
724 }
725
reiserfs_fs_super_reopen(reiserfs_fs_t * fs)726 int reiserfs_fs_super_reopen(reiserfs_fs_t *fs) {
727 ASSERT(fs != NULL, return 0);
728
729 reiserfs_fs_super_close(fs);
730 return reiserfs_fs_super_open(fs);
731 }
732
reiserfs_fs_super_open(reiserfs_fs_t * fs)733 int reiserfs_fs_super_open(reiserfs_fs_t *fs) {
734 reiserfs_block_t *block;
735
736 ASSERT(fs != NULL, return 0);
737
738 if (fs->super) {
739 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
740 _("Superblock already opened."));
741 return 0;
742 }
743
744 if (reiserfs_fs_journal_opened(fs) && fs->super_off) {
745 if (!(block = reiserfs_journal_read(fs->journal, fs->super_off))) {
746 if (!(block = reiserfs_block_read(fs->dal, fs->super_off))) {
747 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
748 _("Couldn't reopen superblock from journal. %s."),
749 dal_error(fs->dal));
750 return 0;
751 }
752 }
753
754 if (!reiserfs_fs_super_open_check((reiserfs_super_t *)block->data,
755 dal_len(fs->dal), 0))
756 {
757 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
758 _("Invalid superblock has read from the journal."));
759 goto error_free_block;
760 }
761
762 reiserfs_block_set_nr(block, fs->super_off);
763 } else {
764 if (!(block = reiserfs_fs_super_probe(fs->dal, 0)))
765 return 0;
766 }
767
768 if (!(fs->super = libreiserfs_calloc(dal_get_blocksize(fs->dal), 0)))
769 goto error_free_block;
770
771 memcpy(fs->super, block->data, dal_get_blocksize(fs->dal));
772 fs->super_off = reiserfs_block_get_nr(block);
773
774 reiserfs_fs_mark_super_clean(fs);
775 reiserfs_block_free(block);
776
777 return 1;
778
779 error_free_block:
780 reiserfs_block_free(block);
781 error:
782 return 0;
783 }
784
reiserfs_fs_clobber_skipped(dal_t * dal)785 int reiserfs_fs_clobber_skipped(dal_t *dal) {
786 reiserfs_gauge_t *gauge;
787 reiserfs_segment_t segment;
788 reiserfs_block_t *block;
789 size_t orig_blocksize;
790
791 ASSERT(dal != NULL, return 0);
792
793 orig_blocksize = dal_get_blocksize(dal);
794
795 if (!dal_set_blocksize(dal, 1024))
796 goto error;
797
798 #if defined(__sparc__) || defined(__sparcv9)
799 if (!reiserfs_segment_init(&segment, dal, 1, DEFAULT_SUPER_OFFSET / dal_get_blocksize(dal)))
800 goto error;
801 #else
802 if (!reiserfs_segment_init(&segment, dal, 0, DEFAULT_SUPER_OFFSET / dal_get_blocksize(dal)))
803 goto error;
804 #endif
805
806 if ((gauge = libreiserfs_get_gauge())) {
807 libreiserfs_gauge_reset(gauge);
808 libreiserfs_gauge_set_name(gauge, _("initializing skiped area"));
809 }
810
811 if (!reiserfs_segment_fill(&segment, 0,
812 (reiserfs_segment_func_t)reiserfs_callback_segment_gauge, gauge))
813 goto error;
814
815 if (gauge)
816 libreiserfs_gauge_finish(gauge, 1);
817
818 return dal_set_blocksize(dal, orig_blocksize);
819
820 error:
821 dal_set_blocksize(dal, orig_blocksize);
822 return 0;
823 }
824
reiserfs_fs_super_create(reiserfs_fs_t * fs,int format,reiserfs_hash_t hash,const char * label,const char * uuid,size_t blocksize,blk_t start,blk_t len,blk_t fs_len,int relocated)825 int reiserfs_fs_super_create(reiserfs_fs_t *fs, int format, reiserfs_hash_t hash,
826 const char *label, const char *uuid, size_t blocksize, blk_t start,
827 blk_t len, blk_t fs_len, int relocated)
828 {
829 blk_t sb_blk, blk;
830 reiserfs_super_t *sb;
831 reiserfs_block_t *block;
832
833 ASSERT(fs != NULL, return 0);
834
835 reiserfs_fs_bitmap_check_state(fs, return 0);
836
837 if (!reiserfs_fs_clobber_skipped(fs->dal))
838 return 0;
839
840 sb_blk = DEFAULT_SUPER_OFFSET / blocksize;
841
842 if (!(block = reiserfs_block_alloc(fs->dal, sb_blk, 0)))
843 return 0;
844
845 sb = (reiserfs_super_t *)block->data;
846
847 set_sb_umount_state(sb, FS_CLEAN);
848
849 sb->s_v1.sb_block_count = CPU_TO_LE32(fs_len);
850 sb->s_v1.sb_bmap_nr = CPU_TO_LE16((fs_len - 1) / (8 * blocksize) + 1);
851
852 /*
853 Used blocks are: blk-s skipped, super block,
854 bitmap blocks, journal, root block.
855 */
856
857 sb->s_v1.sb_free_blocks = CPU_TO_LE32(fs_len - sb_blk - 1 -
858 (relocated ? 0 : len + 1) - LE16_TO_CPU(sb->s_v1.sb_bmap_nr) - 1);
859
860 sb->s_v1.sb_format = CPU_TO_LE16(format);
861 sb->s_v1.sb_block_size = CPU_TO_LE16(blocksize);
862 sb->s_v1.sb_fs_state = CPU_TO_LE16(FS_CONSISTENT);
863
864 /* Hash function */
865 sb->s_v1.sb_hash_function_code = CPU_TO_LE32(hash);
866
867 /* Updating super signature */
868 reiserfs_fs_super_magic_update(sb, format, relocated);
869
870 if (format == FS_FORMAT_3_6)
871 sb->s_v1.sb_oid_maxsize = CPU_TO_LE16 ((blocksize - SUPER_V2_SIZE) /
872 sizeof (uint32_t) / 2 * 2);
873 else
874 sb->s_v1.sb_oid_maxsize = CPU_TO_LE16 ((blocksize - SUPER_V1_SIZE) /
875 sizeof (uint32_t) / 2 * 2);
876
877 /* Label and uuid */
878 if (label && strlen(label)) {
879 int label_len = strlen(label) < sizeof(sb->s_label) ? strlen(label) :
880 sizeof(sb->s_label) - 1;
881 memcpy(sb->s_label, label, label_len);
882 }
883
884 if (uuid && strlen(uuid)) {
885 int uuid_len = strlen(uuid) < sizeof(sb->s_uuid) ? strlen(uuid) :
886 sizeof(sb->s_uuid) - 1;
887 memcpy(sb->s_uuid, uuid, uuid_len);
888 }
889
890 /* Journal params */
891 reiserfs_journal_params_update(get_sb_jp(sb), start, len, 0,
892 relocated, get_sb_block_size(sb));
893
894 if (!(fs->super = (reiserfs_super_t *)libreiserfs_calloc(blocksize, 0)))
895 goto error_free_block;
896
897 memcpy(fs->super, sb, blocksize);
898
899 fs->super_off = sb_blk;
900 reiserfs_block_free(block);
901
902 /* Marking skiped blocks used and super block as used. */
903 for (blk = 0; blk <= sb_blk; blk++)
904 reiserfs_fs_bitmap_use_block(fs, blk);
905
906 reiserfs_fs_mark_super_dirty(fs);
907 reiserfs_fs_mark_bitmap_dirty(fs);
908
909 return 1;
910
911 error_free_block:
912 reiserfs_block_free(block);
913 error:
914 return 0;
915 }
916
reiserfs_fs_dal(reiserfs_fs_t * fs)917 dal_t *reiserfs_fs_dal(reiserfs_fs_t *fs) {
918 return fs->dal;
919 }
920
reiserfs_fs_set_root(reiserfs_fs_t * fs,blk_t blk)921 int reiserfs_fs_set_root(reiserfs_fs_t *fs, blk_t blk) {
922 ASSERT(fs != NULL, return 0);
923
924 set_sb_root_block(fs->super, blk);
925 reiserfs_fs_mark_super_dirty(fs);
926
927 return 1;
928 }
929
reiserfs_fs_data(reiserfs_fs_t * fs)930 void *reiserfs_fs_data(reiserfs_fs_t *fs) {
931 ASSERT(fs != NULL, return NULL);
932 return fs->data;
933 }
934
reiserfs_fs_set_data(reiserfs_fs_t * fs,void * data)935 void reiserfs_fs_set_data(reiserfs_fs_t *fs, void *data) {
936 ASSERT(fs != NULL, return);
937 fs->data = data;
938 }
939
reiserfs_fs_super_close(reiserfs_fs_t * fs)940 void reiserfs_fs_super_close(reiserfs_fs_t *fs) {
941 ASSERT(fs != NULL, return);
942 libreiserfs_free(fs->super);
943 fs->super = NULL;
944 }
945
reiserfs_fs_super(reiserfs_fs_t * fs)946 reiserfs_super_t *reiserfs_fs_super(reiserfs_fs_t *fs) {
947 ASSERT(fs != NULL, return NULL);
948 return fs->super;
949 }
950
reiserfs_fs_probe(dal_t * dal)951 blk_t reiserfs_fs_probe(dal_t *dal) {
952 blk_t fs_len;
953 reiserfs_block_t *block;
954 reiserfs_super_t *super;
955
956 ASSERT(dal != NULL, return 0);
957
958 dal_set_blocksize(dal, DEFAULT_BLOCK_SIZE);
959
960 if (!(block = reiserfs_fs_super_probe(dal, 1)))
961 return 0;
962
963 super = (reiserfs_super_t *)block->data;
964
965 fs_len = get_sb_block_count(super);
966 reiserfs_block_free(block);
967
968 return fs_len;
969 }
970
reiserfs_fs_resize_check(reiserfs_fs_t * fs)971 static int reiserfs_fs_resize_check(reiserfs_fs_t *fs) {
972 if (!reiserfs_fs_is_resizeable(fs)) {
973 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
974 _("Can't resize old format filesystem."));
975 return 0;
976 }
977
978 reiserfs_fs_bitmap_check_state(fs, return 0);
979
980 if (get_sb_umount_state(fs->super) != FS_CLEAN) {
981 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
982 _("Filesystem isn't in valid state. May be it is not cleanly unmounted."));
983 return 0;
984 }
985
986 return 1;
987 }
988
989 /* Smart resizing stuff */
reiserfs_fs_metadata_move(reiserfs_fs_t * fs,long start,long end)990 static int reiserfs_fs_metadata_move(reiserfs_fs_t *fs, long start, long end) {
991 reiserfs_gauge_t *gauge;
992 reiserfs_segment_t src_segment, dst_segment;
993
994 blk_t old_meta_off = fs->super_off + (start < 0 ? labs(start) : 0);
995 blk_t new_meta_off = fs->super_off + (start < 0 ? 0 : labs(start));
996 blk_t meta_len = 2 + reiserfs_fs_journal_area(fs);
997
998 /* Moving the metadata */
999 if (!reiserfs_segment_init(&src_segment, fs->dal, old_meta_off, old_meta_off +
1000 meta_len))
1001 return 0;
1002
1003 if (!reiserfs_segment_init(&dst_segment, fs->dal, new_meta_off, new_meta_off +
1004 meta_len))
1005 return 0;
1006
1007 if ((gauge = libreiserfs_get_gauge())) {
1008 libreiserfs_gauge_reset(gauge);
1009 libreiserfs_gauge_set_name(gauge, _("relocating metadata"));
1010 }
1011
1012 if (!reiserfs_segment_move(&dst_segment, &src_segment,
1013 (reiserfs_segment_func_t)reiserfs_callback_segment_gauge, gauge))
1014 return 0;
1015
1016 if (gauge)
1017 libreiserfs_gauge_finish(gauge, 1);
1018
1019 return 1;
1020 }
1021
reiserfs_fs_tree_move(reiserfs_fs_t * fs,long start,long end)1022 static blk_t reiserfs_fs_tree_move(reiserfs_fs_t *fs, long start, long end) {
1023 reiserfs_gauge_t *gauge;
1024 reiserfs_segment_t src_segment, dst_segment;
1025
1026 blk_t root_blk;
1027
1028 blk_t old_meta_off = fs->super_off + (start < 0 ? labs(start) : 0);
1029 blk_t new_meta_off = fs->super_off + (start < 0 ? 0 : labs(start));
1030 blk_t meta_len = 2 + reiserfs_fs_journal_area(fs);
1031
1032 /* Moving the tree */
1033 reiserfs_tree_set_offset(fs->tree, (start < 0 ? start : 0));
1034
1035 if (!reiserfs_segment_init(&src_segment, fs->dal, old_meta_off + meta_len,
1036 reiserfs_fs_size(fs) + -start))
1037 return 0;
1038
1039 if (!reiserfs_segment_init(&dst_segment, fs->dal, new_meta_off + meta_len, end))
1040 return 0;
1041
1042 if ((gauge = libreiserfs_get_gauge())) {
1043 libreiserfs_gauge_reset(gauge);
1044 libreiserfs_gauge_set_name(gauge, _("shrinking"));
1045 }
1046
1047 if (!(root_blk = reiserfs_segment_relocate(fs, &dst_segment, fs, &src_segment, 1)))
1048 return 0;
1049
1050 if (gauge)
1051 libreiserfs_gauge_finish(gauge, 1);
1052
1053 reiserfs_tree_set_offset(fs->tree, 0);
1054
1055 return root_blk;
1056 }
1057
reiserfs_fs_resize_smart(reiserfs_fs_t * fs,long start,long end)1058 int reiserfs_fs_resize_smart(reiserfs_fs_t *fs, long start, long end) {
1059 blk_t root_blk, fs_len;
1060 blk_t bitmap_new_size;
1061
1062 if (!reiserfs_fs_resize_check(fs))
1063 return 0;
1064
1065 if (start == 0 && end == (long)get_sb_block_count(fs->super)) {
1066 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
1067 _("New boundaries are the same as previous ones."));
1068 return 0;
1069 }
1070
1071 if (end < start) {
1072 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
1073 _("Invalid boundaries: start=%ld, end=%ld"), start, end);
1074 return 0;
1075 }
1076
1077 fs_len = (blk_t)(end - start);
1078 bitmap_new_size = (fs_len - 1) / (8 * get_sb_block_size(fs->super)) + 1;
1079
1080 /* Check if we are going to shrink */
1081 if (get_sb_block_count(fs->super) > fs_len) {
1082 if (get_sb_block_count(fs->super) - fs_len >
1083 get_sb_free_blocks(fs->super) +
1084 get_sb_bmap_nr(fs->super) - bitmap_new_size)
1085 {
1086 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
1087 _("Can't shrink filesystem. Too many "
1088 "blocks already allocated."));
1089 return 0;
1090 }
1091 }
1092
1093 if (!reiserfs_fs_state_update(fs, FS_CORRUPTED))
1094 return 0;
1095
1096 if (!reiserfs_fs_bitmap_resize(fs, start, end))
1097 return 0;
1098
1099 if (start < 0) {
1100 if (!reiserfs_fs_metadata_move(fs, start, end))
1101 return 0;
1102
1103 if (!(root_blk = reiserfs_fs_tree_move(fs, start, end)))
1104 return 0;
1105 } else {
1106 if (!(root_blk = reiserfs_fs_tree_move(fs, start, end)))
1107 return 0;
1108
1109 if (!reiserfs_fs_metadata_move(fs, start, end))
1110 return 0;
1111 }
1112
1113 fs->super_off = (start <= 0 ? fs->super_off : fs->super_off + start);
1114
1115 set_sb_root_block(fs->super, root_blk);
1116
1117 set_sb_free_blocks(fs->super, get_sb_free_blocks(fs->super) -
1118 (get_sb_block_count(fs->super) - fs_len) + (get_sb_bmap_nr(fs->super) -
1119 bitmap_new_size));
1120
1121 set_sb_block_count(fs->super, fs_len);
1122 set_sb_bmap_nr(fs->super, bitmap_new_size);
1123
1124 reiserfs_fs_mark_bitmap_dirty(fs);
1125 reiserfs_fs_mark_super_dirty(fs);
1126
1127 if (!reiserfs_fs_state_update(fs, FS_CONSISTENT))
1128 return 0;
1129
1130 if (!reiserfs_fs_super_sync(fs))
1131 return 0;
1132
1133 fs->super_off = DEFAULT_SUPER_OFFSET / fs->dal->blocksize;
1134
1135 return 1;
1136 }
1137
1138 /* Dumb resizing stuff */
reiserfs_fs_shrink(reiserfs_fs_t * fs,blk_t fs_len)1139 static int reiserfs_fs_shrink(reiserfs_fs_t *fs, blk_t fs_len) {
1140 blk_t root_blk;
1141 blk_t bitmap_new_size;
1142 reiserfs_gauge_t *gauge;
1143 reiserfs_segment_t src_segment, dst_segment;
1144
1145 bitmap_new_size = (fs_len - 1) / (8 * get_sb_block_size(fs->super)) + 1;
1146
1147 if (get_sb_block_count(fs->super) - fs_len > get_sb_free_blocks(fs->super) +
1148 get_sb_bmap_nr(fs->super) - bitmap_new_size)
1149 {
1150 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
1151 _("Can't shrink filesystem. Too many blocks already allocated."));
1152 return 0;
1153 }
1154
1155 if (!reiserfs_segment_init(&src_segment, fs->dal, fs_len, reiserfs_fs_size(fs)))
1156 return 0;
1157
1158 if (!reiserfs_segment_init(&dst_segment, fs->dal, fs->super_off + 2 +
1159 reiserfs_fs_journal_area(fs), fs_len))
1160 return 0;
1161
1162 if (!reiserfs_fs_state_update(fs, FS_CORRUPTED))
1163 return 0;
1164
1165 if ((gauge = libreiserfs_get_gauge())) {
1166 libreiserfs_gauge_reset(gauge);
1167 libreiserfs_gauge_set_name(gauge, _("shrinking"));
1168 }
1169
1170 if (!(root_blk = reiserfs_segment_relocate(fs, &dst_segment, fs, &src_segment, 0)))
1171 return 0;
1172
1173 if (gauge)
1174 libreiserfs_gauge_finish(gauge, 1);
1175
1176 if (!reiserfs_fs_bitmap_resize(fs, 0, fs_len))
1177 return 0;
1178
1179 set_sb_free_blocks(fs->super, get_sb_free_blocks(fs->super) -
1180 (get_sb_block_count(fs->super) - fs_len) + (get_sb_bmap_nr(fs->super) -
1181 bitmap_new_size));
1182
1183 set_sb_block_count(fs->super, fs_len);
1184 set_sb_bmap_nr(fs->super, bitmap_new_size);
1185
1186 reiserfs_fs_mark_bitmap_dirty(fs);
1187
1188 return reiserfs_fs_state_update(fs, FS_CONSISTENT);
1189 }
1190
reiserfs_fs_expand(reiserfs_fs_t * fs,blk_t fs_len)1191 static int reiserfs_fs_expand(reiserfs_fs_t *fs, blk_t fs_len) {
1192 blk_t bmap_new_blknr, bmap_old_blknr;
1193
1194 if (fs_len > dal_len(fs->dal)) {
1195 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
1196 _("Device is too small for (%lu) blocks."), fs_len);
1197 return 0;
1198 }
1199
1200 bmap_old_blknr = get_sb_bmap_nr(fs->super);
1201
1202 /*
1203 Computing bitmap blocks count in new fs. One bit in bitmap
1204 points to one block.
1205 */
1206 bmap_new_blknr = (fs_len - 1) / (get_sb_block_size(fs->super) * 8) + 1;
1207
1208 if (!reiserfs_fs_state_update(fs, FS_CORRUPTED))
1209 return 0;
1210
1211 if (!reiserfs_fs_bitmap_resize(fs, 0, fs_len))
1212 return 0;
1213
1214 set_sb_free_blocks(fs->super, get_sb_free_blocks(fs->super) +
1215 (fs_len - get_sb_block_count(fs->super)) - (bmap_new_blknr - bmap_old_blknr));
1216
1217 set_sb_block_count(fs->super, fs_len);
1218 set_sb_bmap_nr(fs->super, bmap_new_blknr);
1219
1220 reiserfs_fs_mark_bitmap_dirty(fs);
1221 return reiserfs_fs_state_update(fs, FS_CONSISTENT);
1222 }
1223
reiserfs_fs_resize_dumb(reiserfs_fs_t * fs,blk_t fs_len)1224 int reiserfs_fs_resize_dumb(reiserfs_fs_t *fs, blk_t fs_len) {
1225
1226 ASSERT(fs != NULL, return 0);
1227
1228 if (!reiserfs_fs_resize_check(fs))
1229 return 0;
1230
1231 if (fs_len == get_sb_block_count(fs->super)) {
1232 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
1233 _("New size is the same as previous one."));
1234 return 0;
1235 }
1236
1237 return (fs_len > get_sb_block_count(fs->super) ?
1238 reiserfs_fs_expand(fs, fs_len) : reiserfs_fs_shrink(fs, fs_len));
1239 }
1240
reiserfs_fs_tree_open(reiserfs_fs_t * fs)1241 int reiserfs_fs_tree_open(reiserfs_fs_t *fs) {
1242 ASSERT(fs != NULL, return 0);
1243
1244 if (!(fs->tree = reiserfs_tree_open((void *)fs))) {
1245 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
1246 _("Couldn't open reiserfs tree."));
1247 return 0;
1248 }
1249
1250 return 1;
1251 }
1252
reiserfs_fs_tree_create(reiserfs_fs_t * fs)1253 int reiserfs_fs_tree_create(reiserfs_fs_t *fs) {
1254 ASSERT(fs != NULL, return 0);
1255
1256 reiserfs_fs_bitmap_check_state(fs, return 0);
1257 if (!(fs->tree = reiserfs_tree_create((void *)fs))) {
1258 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
1259 _("Couldn't open reiserfs tree."));
1260 return 0;
1261 }
1262 return 1;
1263 }
1264
reiserfs_fs_tree_close(reiserfs_fs_t * fs)1265 void reiserfs_fs_tree_close(reiserfs_fs_t *fs) {
1266 ASSERT(fs != NULL, return);
1267
1268 if (!fs->tree) {
1269 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
1270 _("Tree isn't opened."));
1271 return;
1272 }
1273 reiserfs_tree_free(fs->tree);
1274 }
1275
reiserfs_fs_tree(reiserfs_fs_t * fs)1276 void *reiserfs_fs_tree(reiserfs_fs_t *fs) {
1277 ASSERT(fs != NULL, return NULL);
1278 return fs->tree;
1279 }
1280
reiserfs_fs_open_as(dal_t * host_dal,dal_t * journal_dal,int with_bitmap)1281 static reiserfs_fs_t *reiserfs_fs_open_as(dal_t *host_dal, dal_t *journal_dal,
1282 int with_bitmap)
1283 {
1284 reiserfs_fs_t *fs;
1285 reiserfs_super_t *sb;
1286
1287 ASSERT(host_dal != NULL, return NULL);
1288
1289 if (!(fs = (reiserfs_fs_t *)libreiserfs_calloc(sizeof(*fs), 0)))
1290 goto error;
1291
1292 fs->dal = host_dal;
1293
1294 if (!reiserfs_fs_super_open(fs))
1295 goto error_free_fs;
1296
1297 if (journal_dal)
1298 dal_set_blocksize(journal_dal, get_sb_block_size(fs->super));
1299
1300 if (with_bitmap && !reiserfs_fs_is_consistent(fs)) {
1301 if (dal_flags(host_dal) & O_RDWR) {
1302 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
1303 _("Filesystem isn't consistent. Couldn't open it for write."));
1304 goto error_free_fs;
1305 }
1306 if (dal_flags(host_dal) & O_RDONLY)
1307 libreiserfs_exception_throw(EXCEPTION_WARNING, EXCEPTION_IGNORE,
1308 _("Filesystem isn't consistent."));
1309 }
1310
1311 if (get_jp_magic(get_sb_jp(fs->super)) != JOURNAL_NEED_TUNE) {
1312 if (reiserfs_fs_journal_relocated(fs) && journal_dal &&
1313 dal_equals(host_dal, journal_dal))
1314 {
1315 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
1316 _("Filesystem has journal on separate device, but specified host device."));
1317 goto error_free_fs;
1318 }
1319
1320 if (journal_dal) {
1321 if (!reiserfs_fs_journal_open(fs, journal_dal))
1322 goto error_free_super;
1323
1324 /* Reopening the superblock that can logged by the journal */
1325 if (!reiserfs_fs_super_reopen(fs))
1326 goto error_free_fs;
1327 }
1328 } else
1329 libreiserfs_exception_throw(EXCEPTION_WARNING, EXCEPTION_IGNORE,
1330 _("Journal was not opened. Journal tuning is needed."));
1331
1332 if (with_bitmap && !reiserfs_fs_bitmap_open(fs))
1333 goto error_free_journal;
1334
1335 if (!reiserfs_fs_tree_open(fs))
1336 goto error_free_journal;
1337
1338 return fs;
1339
1340 error_free_journal:
1341 if (reiserfs_fs_journal_opened(fs))
1342 reiserfs_fs_journal_close(fs);
1343 error_free_super:
1344 reiserfs_fs_super_close(fs);
1345 error_free_fs:
1346 libreiserfs_free(fs);
1347 error:
1348 return NULL;
1349 }
1350
reiserfs_fs_open(dal_t * host_dal,dal_t * journal_dal)1351 reiserfs_fs_t *reiserfs_fs_open(dal_t *host_dal, dal_t *journal_dal) {
1352 return reiserfs_fs_open_as(host_dal, journal_dal, 1);
1353 }
1354
reiserfs_fs_open_fast(dal_t * host_dal,dal_t * journal_dal)1355 reiserfs_fs_t *reiserfs_fs_open_fast(dal_t *host_dal, dal_t *journal_dal) {
1356 return reiserfs_fs_open_as(host_dal, journal_dal, 0);
1357 }
1358
reiserfs_fs_sync(reiserfs_fs_t * fs)1359 int reiserfs_fs_sync(reiserfs_fs_t *fs) {
1360 ASSERT(fs != NULL, return 0);
1361
1362 if (reiserfs_fs_super_dirty(fs) && !reiserfs_fs_super_sync(fs))
1363 return 0;
1364
1365 if (reiserfs_fs_bitmap_opened(fs) && reiserfs_fs_bitmap_dirty(fs) &&
1366 !reiserfs_fs_bitmap_sync(fs))
1367 return 0;
1368
1369 if (reiserfs_fs_journal_opened(fs) && reiserfs_fs_journal_dirty(fs) &&
1370 !reiserfs_fs_journal_sync(fs))
1371 return 0;
1372
1373 return 1;
1374 }
1375
reiserfs_fs_clobber(dal_t * dal)1376 int reiserfs_fs_clobber(dal_t *dal) {
1377 reiserfs_block_t *block;
1378 int i, super_offset[] = {16, 2, -1};
1379
1380 ASSERT(dal != NULL, return 0);
1381
1382 for (i = 0; super_offset[i] != -1; i++) {
1383 if (!(block = reiserfs_block_alloc(dal, super_offset[i], 0)))
1384 return 0;
1385
1386 if (!reiserfs_block_write(dal, block)) {
1387 reiserfs_block_writing_failed(super_offset[i],
1388 dal_error(dal), goto error_free_block);
1389 }
1390
1391 reiserfs_block_free(block);
1392 }
1393
1394 return 1;
1395 error_free_block:
1396 reiserfs_block_free(block);
1397 error:
1398 return 0;
1399 }
1400
reiserfs_fs_create_check(dal_t * host_dal,dal_t * journal_dal,blk_t start,blk_t max_trans,blk_t len,size_t blocksize,int format,reiserfs_hash_t hash,const char * label,const char * uuid,blk_t fs_len,int relocated)1401 static int reiserfs_fs_create_check(dal_t *host_dal, dal_t *journal_dal,
1402 blk_t start, blk_t max_trans, blk_t len, size_t blocksize,
1403 int format, reiserfs_hash_t hash, const char *label, const char *uuid,
1404 blk_t fs_len, int relocated)
1405 {
1406 blk_t dev_len, tree_start;
1407
1408 ASSERT(host_dal != NULL, return 0);
1409
1410 if (!reiserfs_tools_power_of_two(blocksize)) {
1411 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
1412 _("Block size isn't power of two (%d)."), blocksize);
1413 return 0;
1414 }
1415
1416 if (blocksize < 1024) {
1417 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
1418 _("Block size is too small (%d)."), blocksize);
1419 return 0;
1420 }
1421
1422 if (blocksize > DEFAULT_SUPER_OFFSET) {
1423 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
1424 _("Block size is too big (%d)."), blocksize);
1425 return 0;
1426 }
1427
1428 if (fs_len <= 0) {
1429 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
1430 _("Invalid filesystem size (%lu)."), fs_len);
1431 return 0;
1432 }
1433
1434 dev_len = dal_len(host_dal);
1435 if (fs_len > dev_len) {
1436 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
1437 _("Filesystem is too big for device (%lu)."), dev_len);
1438 return 0;
1439 }
1440
1441 tree_start = (DEFAULT_SUPER_OFFSET / dal_get_blocksize(host_dal)) + 2 +
1442 (relocated ? 0 : len + 1);
1443
1444 if (fs_len <= tree_start + 100) {
1445 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
1446 _("Size of file system is too small. It must be at least (%lu) blocks."),
1447 tree_start + 100 + 1);
1448 return 0;
1449 }
1450
1451 return 1;
1452 }
1453
reiserfs_fs_create(dal_t * host_dal,dal_t * journal_dal,blk_t start,blk_t max_trans,blk_t len,size_t blocksize,int format,reiserfs_hash_t hash,const char * label,const char * uuid,blk_t fs_len)1454 reiserfs_fs_t *reiserfs_fs_create(dal_t *host_dal, dal_t *journal_dal,
1455 blk_t start, blk_t max_trans, blk_t len, size_t blocksize, int format,
1456 reiserfs_hash_t hash, const char *label, const char *uuid, blk_t fs_len)
1457 {
1458 reiserfs_fs_t *fs;
1459 reiserfs_block_t *root;
1460 int relocated;
1461
1462 ASSERT(host_dal != NULL, return NULL);
1463
1464 relocated = journal_dal && !dal_equals(host_dal, journal_dal);
1465
1466 if (!reiserfs_fs_create_check(host_dal, journal_dal, start, max_trans,
1467 len, blocksize, format, hash, label, uuid, fs_len, relocated))
1468 return 0;
1469
1470 if (!(fs = (reiserfs_fs_t *)libreiserfs_calloc(sizeof(*fs), 0)))
1471 return NULL;
1472
1473 fs->dal = host_dal;
1474
1475 /*
1476 Creating bitmap. Must be first, because all another code of
1477 reiserfs_fs_create uses it.
1478 */
1479 if (!reiserfs_fs_bitmap_create(fs, blocksize, fs_len))
1480 goto error_free_fs;
1481
1482 /* Creating super */
1483 if (!reiserfs_fs_super_create(fs, format, hash, label, uuid, blocksize,
1484 start, len, fs_len, relocated))
1485 {
1486 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
1487 _("Couldn't create superblock."));
1488 goto error_free_bitmap;
1489 }
1490
1491 /* Creating journal */
1492 if (journal_dal) {
1493 if (!reiserfs_fs_journal_create(fs, journal_dal, start, len, max_trans))
1494 goto error_free_super;
1495 }
1496
1497 /* Creating empty tree */
1498 if (!reiserfs_fs_tree_create(fs))
1499 goto error_free_journal;
1500
1501 /* Synchronizing created filesystem */
1502 if (!reiserfs_fs_sync(fs))
1503 goto error_free_tree;
1504
1505 return fs;
1506
1507 error_free_tree:
1508 reiserfs_fs_tree_close(fs);
1509 error_free_journal:
1510 reiserfs_fs_journal_close(fs);
1511 error_free_super:
1512 reiserfs_fs_super_close(fs);
1513 error_free_bitmap:
1514 reiserfs_fs_bitmap_close(fs);
1515 error_free_fs:
1516 libreiserfs_free(fs);
1517 error:
1518 return NULL;
1519 }
1520
reiserfs_fs_close(reiserfs_fs_t * fs)1521 void reiserfs_fs_close(reiserfs_fs_t *fs) {
1522 ASSERT(fs != NULL, return);
1523
1524 if (!reiserfs_fs_sync(fs))
1525 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
1526 _("Couldn't synchronize filesystem."));
1527
1528 if (reiserfs_fs_journal_opened(fs))
1529 reiserfs_fs_journal_close(fs);
1530
1531 if (reiserfs_fs_bitmap_opened(fs))
1532 reiserfs_fs_bitmap_close(fs);
1533
1534 reiserfs_fs_tree_close(fs);
1535 reiserfs_fs_super_close(fs);
1536
1537 libreiserfs_free(fs);
1538 }
1539
reiserfs_fs_is_consistent(reiserfs_fs_t * fs)1540 int reiserfs_fs_is_consistent(reiserfs_fs_t *fs) {
1541 ASSERT(fs != NULL, return 0);
1542
1543 return (get_sb_fs_state(fs->super) == FS_CONSISTENT &&
1544 get_sb_umount_state(fs->super) == FS_CLEAN);
1545 }
1546
reiserfs_fs_is_resizeable(reiserfs_fs_t * fs)1547 int reiserfs_fs_is_resizeable(reiserfs_fs_t *fs) {
1548 return fs->super_off != 2;
1549 }
1550
reiserfs_fs_hash_func(reiserfs_hash_t hash_code)1551 reiserfs_hash_func_t reiserfs_fs_hash_func(reiserfs_hash_t hash_code) {
1552 switch (hash_code) {
1553 case TEA_HASH: return __tea_hash_func;
1554 case YURA_HASH: return __yura_hash_func;
1555 case R5_HASH: return __r5_hash_func;
1556 default: return NULL;
1557 }
1558 }
1559
reiserfs_fs_hash_value(reiserfs_fs_t * fs,const char * name)1560 uint32_t reiserfs_fs_hash_value(reiserfs_fs_t *fs, const char *name) {
1561 uint32_t hash_value;
1562 reiserfs_hash_func_t hash_func;
1563
1564 ASSERT(fs != NULL, return 0);
1565 ASSERT(name != NULL, return 0);
1566
1567 if (!strcmp(name, "."))
1568 return DOT_OFFSET;
1569
1570 if (!strcmp(name, ".."))
1571 return DOT_DOT_OFFSET;
1572
1573 hash_func = reiserfs_fs_hash_func(reiserfs_fs_hash(fs));
1574 hash_value = hash_func(name, strlen(name));
1575
1576 hash_value = GET_HASH_VALUE(hash_value);
1577
1578 if (hash_value == 0)
1579 hash_value = 128;
1580
1581 return hash_value;
1582 }
1583
reiserfs_fs_copy(reiserfs_fs_t * src_fs,dal_t * dst_dal)1584 reiserfs_fs_t *reiserfs_fs_copy(reiserfs_fs_t *src_fs, dal_t *dst_dal) {
1585 blk_t root_blk;
1586 reiserfs_fs_t *dst_fs;
1587 reiserfs_gauge_t *gauge;
1588 char label[16], uuid[16];
1589 blk_t needed_blocks, dst_blocks;
1590
1591 reiserfs_segment_t src_segment, dst_segment;
1592
1593 ASSERT(src_fs != NULL, return NULL);
1594 ASSERT(dst_dal != NULL, return NULL);
1595
1596 reiserfs_fs_bitmap_check_state(src_fs, return 0);
1597
1598 if (dal_get_blocksize(src_fs->dal) != dal_get_blocksize(dst_dal)) {
1599 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
1600 _("Block sizes for source and destination devices are different. "
1601 "Source: %d, destination: %d."), dal_get_blocksize(src_fs->dal),
1602 dal_get_blocksize(dst_dal));
1603 goto error;
1604 }
1605
1606 if (!reiserfs_fs_is_consistent(src_fs)) {
1607 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
1608 _("Source filesystem isn't consistent."));
1609 goto error;
1610 }
1611
1612 dst_blocks = dal_len(dst_dal);
1613 needed_blocks = reiserfs_fs_bitmap_used(src_fs);
1614
1615 if (dst_blocks < needed_blocks) {
1616 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL,
1617 _("Device is too small for (%lu) blocks."), needed_blocks);
1618 goto error;
1619 }
1620
1621 memset(label, 0, sizeof(label));
1622 memset(uuid, 0, sizeof(uuid));
1623
1624 /* Creating empty filesystem on given device */
1625 if (!(dst_fs = reiserfs_fs_create(dst_dal, dst_dal, 0,
1626 get_jp_max_trans_len(get_sb_jp(src_fs->super)),
1627 get_jp_len(get_sb_jp(src_fs->super)), get_sb_block_size(src_fs->super),
1628 get_sb_format(src_fs->super), get_sb_hash_code(src_fs->super), label,
1629 uuid, dal_len(dst_dal))))
1630 goto error;
1631
1632 if (!reiserfs_segment_init(&src_segment, src_fs->dal, src_fs->super_off + 2 +
1633 reiserfs_fs_journal_area(src_fs), reiserfs_fs_size(src_fs)))
1634 goto error;
1635
1636 if (!reiserfs_segment_init(&dst_segment, dst_fs->dal, dst_fs->super_off + 2 +
1637 reiserfs_fs_journal_area(dst_fs), reiserfs_fs_size(dst_fs)))
1638 goto error;
1639
1640 /* Marking dst_fs as corrupted */
1641 if (!reiserfs_fs_state_update(dst_fs, FS_CORRUPTED))
1642 goto error_free_dst_fs;
1643
1644 if ((gauge = libreiserfs_get_gauge())) {
1645 libreiserfs_gauge_reset(gauge);
1646 libreiserfs_gauge_set_name(gauge, _("copying"));
1647 }
1648
1649 reiserfs_fs_bitmap_unuse_block(dst_fs, get_sb_root_block(dst_fs->super));
1650
1651 if (!(root_blk = reiserfs_segment_relocate(dst_fs, &dst_segment,
1652 src_fs, &src_segment, 0)))
1653 goto error_free_dst_fs;
1654
1655 if (gauge)
1656 libreiserfs_gauge_finish(gauge, 1);
1657
1658 set_sb_root_block(dst_fs->super, root_blk);
1659
1660 set_sb_free_blocks (dst_fs->super, reiserfs_fs_bitmap_unused(dst_fs));
1661 dst_fs->super->s_v1.sb_tree_height = src_fs->super->s_v1.sb_tree_height;
1662
1663 /* Marking dst_fs as consistent */
1664 if (!reiserfs_fs_state_update(dst_fs, FS_CONSISTENT))
1665 goto error_free_dst_fs;
1666
1667 return dst_fs;
1668
1669 error_free_dst_fs:
1670 reiserfs_fs_close(dst_fs);
1671 error:
1672 return NULL;
1673 }
1674
reiserfs_fs_label(reiserfs_fs_t * fs)1675 char *reiserfs_fs_label(reiserfs_fs_t *fs) {
1676 ASSERT(fs != NULL, return NULL);
1677 return (reiserfs_fs_format(fs) == FS_FORMAT_3_6 ? fs->super->s_label : NULL);
1678 }
1679
reiserfs_fs_label_update(reiserfs_fs_t * fs,const char * label)1680 void reiserfs_fs_label_update(reiserfs_fs_t *fs, const char *label) {
1681 ASSERT(fs != NULL, return);
1682
1683 if (reiserfs_fs_format(fs) == FS_FORMAT_3_5)
1684 return;
1685
1686 if (label) {
1687 int label_len = (strlen(label) < sizeof(fs->super->s_label) ? strlen(label) :
1688 sizeof(fs->super->s_label) - 1);
1689
1690 memcpy(fs->super->s_label, label, label_len);
1691 } else
1692 memset(fs->super->s_label, 0, sizeof(fs->super->s_label));
1693
1694 reiserfs_fs_mark_super_dirty(fs);
1695 }
1696
reiserfs_fs_uuid(reiserfs_fs_t * fs)1697 char *reiserfs_fs_uuid(reiserfs_fs_t *fs) {
1698 ASSERT(fs != NULL, return NULL);
1699 return (reiserfs_fs_format(fs) == FS_FORMAT_3_6 ? fs->super->s_uuid : NULL);
1700 }
1701
reiserfs_fs_uuid_update(reiserfs_fs_t * fs,const char * uuid)1702 void reiserfs_fs_uuid_update(reiserfs_fs_t *fs, const char *uuid) {
1703 ASSERT(fs != NULL, return);
1704
1705 if (reiserfs_fs_format(fs) == FS_FORMAT_3_5)
1706 return;
1707
1708 if (uuid) {
1709 int uuid_len = (strlen(uuid) < sizeof(fs->super->s_uuid) ? strlen(uuid) :
1710 sizeof(fs->super->s_uuid) - 1);
1711
1712 memcpy(fs->super->s_uuid, uuid, uuid_len);
1713 } else
1714 memset(fs->super->s_uuid, 0, sizeof(fs->super->s_uuid));
1715
1716 reiserfs_fs_mark_super_dirty(fs);
1717 }
1718
reiserfs_fs_host_dal(reiserfs_fs_t * fs)1719 dal_t *reiserfs_fs_host_dal(reiserfs_fs_t *fs) {
1720 ASSERT(fs != NULL, return NULL);
1721 return fs->dal;
1722 }
1723
1724 /* Format functions */
1725 static char *reiserfs_long_formats[] = {"reiserfs 3.5", "unknown", "reiserfs 3.6"};
1726 static char *reiserfs_short_formats[] = {"3.5", "unknown", "3.6"};
1727
reiserfs_fs_format(reiserfs_fs_t * fs)1728 int reiserfs_fs_format(reiserfs_fs_t *fs) {
1729 ASSERT(fs != NULL, return -1);
1730 return get_sb_format(fs->super);
1731 }
1732
reiserfs_fs_long_format_str(int format)1733 const char *reiserfs_fs_long_format_str(int format) {
1734 if (format < 0 || format > 2)
1735 return NULL;
1736
1737 return reiserfs_long_formats[format];
1738 }
1739
reiserfs_fs_short_format_str(int format)1740 const char *reiserfs_fs_short_format_str(int format) {
1741 if (format < 0 || format > 2)
1742 return NULL;
1743
1744 return reiserfs_short_formats[format];
1745 }
1746
reiserfs_fs_format_from_str(const char * format)1747 int reiserfs_fs_format_from_str(const char *format) {
1748 int i;
1749
1750 ASSERT(format != NULL, return -1);
1751
1752 for (i = 0; i < 3; i++) {
1753 if (!strcmp(reiserfs_short_formats[i], format))
1754 return i;
1755 }
1756 return -1;
1757 }
1758
1759 /* Hashes */
1760 static char *reiserfs_hashes[] = {"unknown", "tea", "yura", "r5"};
1761
reiserfs_fs_hash(reiserfs_fs_t * fs)1762 reiserfs_hash_t reiserfs_fs_hash(reiserfs_fs_t *fs) {
1763 ASSERT(fs != NULL, return 0);
1764 return get_sb_hash_code(fs->super);
1765 }
1766
reiserfs_fs_hash_str(reiserfs_hash_t hash)1767 const char *reiserfs_fs_hash_str(reiserfs_hash_t hash) {
1768 if (hash > 4) return NULL;
1769 return reiserfs_hashes[hash];
1770 }
1771
reiserfs_fs_hash_from_str(const char * hash)1772 reiserfs_hash_t reiserfs_fs_hash_from_str(const char *hash) {
1773 int i;
1774
1775 ASSERT(hash != NULL, return 0);
1776 for (i = 0; i < 4; i++) {
1777 if (!strcmp(reiserfs_hashes[i], hash))
1778 return (reiserfs_hash_t)i;
1779 }
1780 return 0;
1781 }
1782
1783 static char *filesystem_states[] = {"consistent", "corrupted"};
1784
reiserfs_fs_fs_state(reiserfs_fs_t * fs)1785 uint32_t reiserfs_fs_fs_state(reiserfs_fs_t *fs) {
1786 ASSERT(fs != NULL, return 0);
1787 return get_sb_fs_state(fs->super);
1788 }
1789
reiserfs_fs_state_update(reiserfs_fs_t * fs,uint32_t state)1790 int reiserfs_fs_state_update(reiserfs_fs_t *fs, uint32_t state) {
1791 ASSERT(fs != NULL, return 0);
1792
1793 set_sb_fs_state(fs->super, state);
1794
1795 return reiserfs_fs_super_sync(fs);
1796 }
1797
reiserfs_fs_state_str(uint32_t state)1798 const char *reiserfs_fs_state_str(uint32_t state) {
1799 if (state > 1) return NULL;
1800 return filesystem_states[state];
1801 }
1802
reiserfs_fs_block_size(reiserfs_fs_t * fs)1803 size_t reiserfs_fs_block_size(reiserfs_fs_t *fs) {
1804 ASSERT(fs != NULL, return 0);
1805 return get_sb_block_size(fs->super);
1806 }
1807
reiserfs_fs_size(reiserfs_fs_t * fs)1808 blk_t reiserfs_fs_size(reiserfs_fs_t *fs) {
1809 ASSERT(fs != NULL, return 0);
1810 return get_sb_block_count(fs->super);
1811 }
1812
reiserfs_fs_min_size(reiserfs_fs_t * fs)1813 blk_t reiserfs_fs_min_size(reiserfs_fs_t *fs) {
1814 ASSERT(fs != NULL, return 0);
1815 return get_sb_block_count(fs->super) - get_sb_free_blocks(fs->super) -
1816 (get_sb_free_blocks(fs->super) / (8 * reiserfs_fs_block_size(fs)));
1817 }
1818
reiserfs_fs_free_size(reiserfs_fs_t * fs)1819 blk_t reiserfs_fs_free_size(reiserfs_fs_t *fs) {
1820 ASSERT(fs != NULL, return 0);
1821 return get_sb_free_blocks(fs->super);
1822 }
1823
reiserfs_fs_metadata_size(reiserfs_fs_t * fs)1824 blk_t reiserfs_fs_metadata_size(reiserfs_fs_t *fs) {
1825 ASSERT(fs != NULL, return 0);
1826 return fs->super_off + get_sb_bmap_nr(fs->super) + reiserfs_fs_journal_area(fs);
1827 }
1828
reiserfs_fs_tree_height(reiserfs_fs_t * fs)1829 uint32_t reiserfs_fs_tree_height(reiserfs_fs_t *fs) {
1830 ASSERT(fs != NULL, return 0);
1831 return get_sb_tree_height(fs->super);
1832 }
1833
1834