/* * Copyright 1998 Hans Reiser */ /*#include #include */ /*#include #include "../include/reiserfs_fs.h" #include "../include/reiserfs_fs_sb.h" #include "../include/reiserfslib.h"*/ #include "fsck.h" /* there is a situation, when we overwrite contents of unformatted node with direct item. One unformatted node can be overwritten several times by direct items */ /* struct overwritten_unfm_segment { int ous_begin; int ous_end; struct overwritten_unfm_segment * ous_next; }; */ struct overwritten_unfm { unsigned long ou_unfm_ptr; /* block number of unfm node */ unsigned long ou_dir_id; unsigned long ou_objectid; /* key corresponding to an unfm node */ unsigned long ou_offset; struct overwritten_unfm_segment * ou_segments; /* list of segmens, than have been overwritten in ths unfm node */ }; struct overwritten_unfm ** g_overwritten_unfms; int g_overwritten_unfms_amount; /* number of unformatted nodes, which contain direct items */ /* adds segment to the single linked list of segments sorted by begin field. Retuns pointer to first element of list */ static struct overwritten_unfm_segment * add_segment (struct overwritten_unfm_segment * first, int begin, int end) { struct overwritten_unfm_segment * new, * next, * prev; new = getmem (sizeof (struct overwritten_unfm_segment)); new->ous_begin = begin; new->ous_end = end; new->ous_next = 0; next = first; prev = 0; while (next) { if (next->ous_begin > begin) break; prev = next; next = next->ous_next; } if (prev == 0) { /* insert into head of list */ first = new; } else { prev->ous_next = new; } new->ous_next = next; return first; } /* input parameter `list_head` - first element of overlapping segments sorted by left edge `unoverwritten_segment` - returned by previous call of get_unoverwritten_segment or (-2,-2) if called first time */ /* returns 1 and segment unoverwritten by elements of list `list_head` 0 if there isno such segment */ int get_unoverwritten_segment (struct overwritten_unfm_segment * list_head, struct overwritten_unfm_segment * unoverwritten_segment) { int end; /* look for segment, which has begin field greater than end of previous interval */ while (list_head->ous_begin <= unoverwritten_segment->ous_end) { list_head = list_head->ous_next; } /* look for the end of the continuous region covered by otrezkami */ end = list_head->ous_end; while (list_head->ous_next) { if (list_head->ous_next->ous_begin > end + 1) /* intreval found */ break; if (list_head->ous_next->ous_end > end) end = list_head->ous_next->ous_end; list_head = list_head->ous_next; } /* ok, between segment and segment->next we have an interval (segment->next != 0) */ if (list_head->ous_next != 0) { unoverwritten_segment->ous_begin = end + 1; unoverwritten_segment->ous_end = list_head->ous_next->ous_begin - 1; return 1; } return 0; } void print_segments (struct overwritten_unfm_segment * list_head) { struct overwritten_unfm_segment * cur; cur = list_head; while (cur) { printf ("%s%d %d%s", cur == list_head ? "(" : "", cur->ous_begin, cur->ous_end, cur->ous_next ? ", " : ")\n"); cur = cur->ous_next; } } /* this prepare list of segments to extracting of unoverwritten segments */ struct overwritten_unfm_segment * find_overwritten_unfm (unsigned long unfm, int length, struct overwritten_unfm_segment * segment_to_init) { int i; for (i = 0; i < g_overwritten_unfms_amount && g_overwritten_unfms[i] != 0; i ++) if (g_overwritten_unfms[i]->ou_unfm_ptr == unfm) { if (g_overwritten_unfms[i]->ou_segments == 0) die ("find_overwritten_unfm: no segment found"); g_overwritten_unfms[i]->ou_segments = add_segment (g_overwritten_unfms[i]->ou_segments, -1, -1); add_segment (g_overwritten_unfms[i]->ou_segments, length, length); segment_to_init->ous_begin = -2; segment_to_init->ous_end = -2; return g_overwritten_unfms[i]->ou_segments; } return 0; } struct overwritten_unfm * look_for_overwritten_unfm (__u32 unfm) { int i; for (i = 0; i < g_overwritten_unfms_amount && g_overwritten_unfms[i] != 0; i ++) if (g_overwritten_unfms[i]->ou_unfm_ptr == unfm) return g_overwritten_unfms[i]; return 0; } #define GROW_BY 10 struct overwritten_unfm * add_overwritten_unfm (unsigned long unfm, struct item_head * direct_ih) { int i; for (i = 0; i < g_overwritten_unfms_amount && g_overwritten_unfms[i] != 0; i ++) { if (g_overwritten_unfms[i]->ou_unfm_ptr == unfm) return g_overwritten_unfms[i]; } if (i == g_overwritten_unfms_amount) { g_overwritten_unfms = expandmem (g_overwritten_unfms, sizeof (struct overwritten_unfm *) * i, sizeof (struct overwritten_unfm *) * GROW_BY); g_overwritten_unfms_amount += GROW_BY; } g_overwritten_unfms[i] = getmem (sizeof (struct overwritten_unfm)); g_overwritten_unfms[i]->ou_unfm_ptr = unfm; g_overwritten_unfms[i]->ou_dir_id = direct_ih->ih_key.k_dir_id; g_overwritten_unfms[i]->ou_objectid = direct_ih->ih_key.k_objectid; g_overwritten_unfms[i]->ou_offset = get_offset(&direct_ih->ih_key) - (get_offset(&direct_ih->ih_key) - 1) % fs->s_blocksize; return g_overwritten_unfms[i]; } void save_unfm_overwriting (unsigned long unfm, struct item_head * direct_ih) { struct overwritten_unfm * ov_unfm; /* add new overwritten unfm or return existing one */ ov_unfm = add_overwritten_unfm (unfm, direct_ih); ov_unfm->ou_segments = add_segment (ov_unfm->ou_segments, (get_offset(&direct_ih->ih_key) - 1) % fs->s_blocksize, (get_offset(&direct_ih->ih_key) - 1) % fs->s_blocksize + ih_item_len (direct_ih) - 1); } void free_overwritten_unfms (void) { int i; for (i = 0; i < g_overwritten_unfms_amount && g_overwritten_unfms[i]; i ++) { /* free all segments */ while (g_overwritten_unfms[i]->ou_segments) { struct overwritten_unfm_segment * tmp; tmp = g_overwritten_unfms[i]->ou_segments->ous_next; freemem (g_overwritten_unfms[i]->ou_segments); g_overwritten_unfms[i]->ou_segments = tmp; } /* free struct overwritten_unfm */ freemem (g_overwritten_unfms[i]); } /* free array of pointers to overwritten unfms */ if (g_overwritten_unfms) freemem (g_overwritten_unfms); }