2 * badblocks.c --- routines to manipulate the bad block structure
4 * Copyright (C) 1994, 1995, 1996 Theodore Ts'o.
7 * This file may be redistributed under the terms of the GNU Library
8 * General Public License, version 2.
25 #include <sys/types.h>
32 * Helper function for making a badblocks list
34 static errcode_t make_u32_list(int size, int num, __u32 *list,
40 retval = ext2fs_get_mem(sizeof(struct ext2_struct_u32_list), &bb);
43 memset(bb, 0, sizeof(struct ext2_struct_u32_list));
44 bb->magic = EXT2_ET_MAGIC_BADBLOCKS_LIST;
45 bb->size = size ? size : 10;
47 retval = ext2fs_get_array(bb->size, sizeof(blk_t), &bb->list);
53 memcpy(bb->list, list, bb->size * sizeof(blk_t));
55 memset(bb->list, 0, bb->size * sizeof(blk_t));
60 static inline int insert_ok(blk_t *array, int cnt, blk_t new)
62 return (cnt == 0 || array[cnt - 1] != new);
66 * Merge list from src to dest
68 static errcode_t merge_u32_list(ext2_u32_list src, ext2_u32_list dest)
71 int src_count = src->num;
72 int dest_count = dest->num;
73 int size = src_count + dest_count;
74 int size_entry = sizeof(blk_t);
76 blk_t *src_array = src->list;
77 blk_t *dest_array = dest->list;
85 retval = ext2fs_get_array(size, size_entry, &array);
90 * It is possible that src list and dest list could be
91 * duplicated when merging badblocks.
93 while (src_index < src_count || dest_index < dest_count) {
94 if (src_index >= src_count) {
95 for (; dest_index < dest_count; dest_index++)
96 if (insert_ok(array, uniq_cnt, dest_array[dest_index]))
97 array[uniq_cnt++] = dest_array[dest_index];
100 if (dest_index >= dest_count) {
101 for (; src_index < src_count; src_index++)
102 if (insert_ok(array, uniq_cnt, src_array[src_index]))
103 array[uniq_cnt++] = src_array[src_index];
106 if (src_array[src_index] < dest_array[dest_index]) {
107 if (insert_ok(array, uniq_cnt, src_array[src_index]))
108 array[uniq_cnt++] = src_array[src_index];
110 } else if (src_array[src_index] > dest_array[dest_index]) {
111 if (insert_ok(array, uniq_cnt, dest_array[dest_index]))
112 array[uniq_cnt++] = dest_array[dest_index];
115 if (insert_ok(array, uniq_cnt, dest_array[dest_index]))
116 array[uniq_cnt++] = dest_array[dest_index];
122 ext2fs_free_mem(&dest->list);
124 dest->num = uniq_cnt;
131 * This procedure creates an empty u32 list.
133 errcode_t ext2fs_u32_list_create(ext2_u32_list *ret, int size)
135 return make_u32_list(size, 0, 0, ret);
139 * This procedure creates an empty badblocks list.
141 errcode_t ext2fs_badblocks_list_create(ext2_badblocks_list *ret, int size)
143 return make_u32_list(size, 0, 0, (ext2_badblocks_list *) ret);
148 * This procedure copies a badblocks list
150 errcode_t ext2fs_u32_copy(ext2_u32_list src, ext2_u32_list *dest)
152 return make_u32_list(src->size, src->num, src->list, dest);
155 errcode_t ext2fs_badblocks_copy(ext2_badblocks_list src,
156 ext2_badblocks_list *dest)
158 return ext2fs_u32_copy((ext2_u32_list) src,
159 (ext2_u32_list *) dest);
162 errcode_t ext2fs_badblocks_merge(ext2_badblocks_list src,
163 ext2_badblocks_list dest)
165 return merge_u32_list((ext2_u32_list) src,
166 (ext2_u32_list) dest);
170 * This procedure frees a badblocks list.
172 * (note: moved to closefs.c)
177 * This procedure adds a block to a badblocks list.
179 errcode_t ext2fs_u32_list_add(ext2_u32_list bb, __u32 blk)
183 unsigned long old_size;
185 EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST);
187 if (bb->num >= bb->size) {
188 old_size = bb->size * sizeof(__u32);
190 retval = ext2fs_resize_mem(old_size, bb->size * sizeof(__u32),
199 * Add special case code for appending to the end of the list
202 if ((bb->num != 0) && (bb->list[i] == blk))
204 if ((bb->num == 0) || (bb->list[i] < blk)) {
205 bb->list[bb->num++] = blk;
210 for (i=0; i < bb->num; i++) {
211 if (bb->list[i] == blk)
213 if (bb->list[i] > blk) {
218 for (i=bb->num; i > j; i--)
219 bb->list[i] = bb->list[i-1];
225 errcode_t ext2fs_badblocks_list_add(ext2_badblocks_list bb, blk_t blk)
227 return ext2fs_u32_list_add((ext2_u32_list) bb, (__u32) blk);
231 * This procedure finds a particular block is on a badblocks
234 int ext2fs_u32_list_find(ext2_u32_list bb, __u32 blk)
238 if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
246 if (blk == bb->list[low])
248 if (blk == bb->list[high])
252 mid = ((unsigned)low + (unsigned)high)/2;
253 if (mid == low || mid == high)
255 if (blk == bb->list[mid])
257 if (blk < bb->list[mid])
266 * This procedure tests to see if a particular block is on a badblocks
269 int ext2fs_u32_list_test(ext2_u32_list bb, __u32 blk)
271 if (ext2fs_u32_list_find(bb, blk) < 0)
277 int ext2fs_badblocks_list_test(ext2_badblocks_list bb, blk_t blk)
279 return ext2fs_u32_list_test((ext2_u32_list) bb, (__u32) blk);
284 * Remove a block from the badblock list
286 int ext2fs_u32_list_del(ext2_u32_list bb, __u32 blk)
293 remloc = ext2fs_u32_list_find(bb, blk);
297 for (i = remloc ; i < bb->num-1; i++)
298 bb->list[i] = bb->list[i+1];
303 void ext2fs_badblocks_list_del(ext2_u32_list bb, __u32 blk)
305 ext2fs_u32_list_del(bb, blk);
308 errcode_t ext2fs_u32_list_iterate_begin(ext2_u32_list bb,
309 ext2_u32_iterate *ret)
311 ext2_u32_iterate iter;
314 EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST);
316 retval = ext2fs_get_mem(sizeof(struct ext2_struct_u32_iterate), &iter);
320 iter->magic = EXT2_ET_MAGIC_BADBLOCKS_ITERATE;
327 errcode_t ext2fs_badblocks_list_iterate_begin(ext2_badblocks_list bb,
328 ext2_badblocks_iterate *ret)
330 return ext2fs_u32_list_iterate_begin((ext2_u32_list) bb,
331 (ext2_u32_iterate *) ret);
335 int ext2fs_u32_list_iterate(ext2_u32_iterate iter, __u32 *blk)
339 if (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE)
344 if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
347 if (iter->ptr < bb->num) {
348 *blk = bb->list[iter->ptr++];
355 int ext2fs_badblocks_list_iterate(ext2_badblocks_iterate iter, blk_t *blk)
357 return ext2fs_u32_list_iterate((ext2_u32_iterate) iter,
362 void ext2fs_u32_list_iterate_end(ext2_u32_iterate iter)
364 if (!iter || (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE))
368 ext2fs_free_mem(&iter);
371 void ext2fs_badblocks_list_iterate_end(ext2_badblocks_iterate iter)
373 ext2fs_u32_list_iterate_end((ext2_u32_iterate) iter);
377 int ext2fs_u32_list_equal(ext2_u32_list bb1, ext2_u32_list bb2)
379 EXT2_CHECK_MAGIC(bb1, EXT2_ET_MAGIC_BADBLOCKS_LIST);
380 EXT2_CHECK_MAGIC(bb2, EXT2_ET_MAGIC_BADBLOCKS_LIST);
382 if (bb1->num != bb2->num)
385 if (memcmp(bb1->list, bb2->list, bb1->num * sizeof(blk_t)) != 0)
390 int ext2fs_badblocks_equal(ext2_badblocks_list bb1, ext2_badblocks_list bb2)
392 return ext2fs_u32_list_equal((ext2_u32_list) bb1,
393 (ext2_u32_list) bb2);
396 int ext2fs_u32_list_count(ext2_u32_list bb)