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