Whamcloud - gitweb
Fix bug in resize2fs which caused it to fail on filesystems with a
authorTheodore Ts'o <tytso@mit.edu>
Tue, 24 Jun 2003 21:34:02 +0000 (17:34 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Tue, 24 Jun 2003 21:34:02 +0000 (17:34 -0400)
non-empty bad block list.  Resize2fs now discards any blocks on the
badblock list which are no longer part of the filesystem as the result
of a filesystem shrink.  (Note: this means that shrinking and then
enlarging a filesystem is no longer a reversible operation;
information about bad blocks in the part of the filesystem
which is to be chopped off will be lost.)

lib/ext2fs/ChangeLog
lib/ext2fs/badblocks.c
lib/ext2fs/ext2fs.h
lib/ext2fs/tst_badblocks.c
resize/ChangeLog
resize/resize2fs.c

index d9a5019..76102e5 100644 (file)
@@ -1,3 +1,11 @@
+2003-06-24    <tytso@snap.thunk.org>
+
+       * badblocks.c, ext2fs.h (ext2fs_u32_list_find,
+               ext2fs_u32_list_test, ext2fs_u32_list_del,
+               ext2fs_badblocks_list_del): Add functions to delete a
+               block from the badblocks list.
+       * tst_badblocks.c: Add test cases for ext2fs_badblocks_list_del().
+
 2003-05-21  Theodore Ts'o  <tytso@mit.edu>
 
        * getsectsize.c (ext2fs_get_device_sectsize): New function which
index 7e1d24f..9fda70c 100644 (file)
@@ -156,41 +156,51 @@ errcode_t ext2fs_badblocks_list_add(ext2_badblocks_list bb, blk_t blk)
        return ext2fs_u32_list_add((ext2_u32_list) bb, (__u32) blk);
 }
 
-
-
 /*
- * This procedure tests to see if a particular block is on a badblocks
+ * This procedure finds a particular block is on a badblocks
  * list.
  */
-int ext2fs_u32_list_test(ext2_u32_list bb, __u32 blk)
+int ext2fs_u32_list_find(ext2_u32_list bb, __u32 blk)
 {
        int     low, high, mid;
 
        if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
-               return 0;
+               return -1;
 
        if (bb->num == 0)
-               return 0;
+               return -1;
 
        low = 0;
        high = bb->num-1;
        if (blk == bb->list[low])
-               return 1;
+               return low;
        if (blk == bb->list[high])
-               return 1;
+               return high;
 
        while (low < high) {
                mid = (low+high)/2;
                if (mid == low || mid == high)
                        break;
                if (blk == bb->list[mid])
-                       return 1;
+                       return mid;
                if (blk < bb->list[mid])
                        high = mid;
                else
                        low = mid;
        }
-       return 0;
+       return -1;
+}
+
+/*
+ * This procedure tests to see if a particular block is on a badblocks
+ * list.
+ */
+int ext2fs_u32_list_test(ext2_u32_list bb, __u32 blk)
+{
+       if (ext2fs_u32_list_find(bb, blk) < 0)
+               return 0;
+       else
+               return 1;
 }
 
 int ext2fs_badblocks_list_test(ext2_badblocks_list bb, blk_t blk)
@@ -199,6 +209,31 @@ int ext2fs_badblocks_list_test(ext2_badblocks_list bb, blk_t blk)
 }
 
 
+/*
+ * Remove a block from the badblock list
+ */
+int ext2fs_u32_list_del(ext2_u32_list bb, __u32 blk)
+{
+       int     remloc, i;
+
+       if (bb->num == 0)
+               return -1;
+
+       remloc = ext2fs_u32_list_find(bb, blk);
+       if (remloc < 0)
+               return -1;
+
+       for (i = remloc ; i < bb->num-1; i++)
+               bb->list[i] = bb->list[i+1];
+       bb->num--;
+       return 0;
+}
+
+void ext2fs_badblocks_list_del(ext2_u32_list bb, __u32 blk)
+{
+       ext2fs_u32_list_del(bb, blk);
+}
+
 errcode_t ext2fs_u32_list_iterate_begin(ext2_u32_list bb,
                                        ext2_u32_iterate *ret)
 {
index cd9344d..d15d08a 100644 (file)
@@ -491,6 +491,8 @@ extern errcode_t ext2fs_badblocks_list_add(ext2_badblocks_list bb,
                                           blk_t blk);
 extern int ext2fs_badblocks_list_test(ext2_badblocks_list bb,
                                    blk_t blk);
+extern int ext2fs_u32_list_del(ext2_u32_list bb, __u32 blk);
+extern void ext2fs_badblocks_list_del(ext2_u32_list bb, __u32 blk);
 extern errcode_t
        ext2fs_badblocks_list_iterate_begin(ext2_badblocks_list bb,
                                            ext2_badblocks_iterate *ret);
index 2ae3585..a42e4cd 100644 (file)
@@ -25,6 +25,9 @@
 #include "ext2_fs.h"
 #include "ext2fs.h"
 
+#define ADD_BLK        0x0001
+#define DEL_BLK        0x0002
+
 blk_t test1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0 };
 blk_t test2[] = { 11, 10, 9, 8, 7, 6, 5, 4, 3, 3, 2, 1 };
 blk_t test3[] = { 3, 1, 4, 5, 9, 2, 7, 10, 5, 6, 10, 8, 0 };
@@ -44,6 +47,20 @@ blk_t test4a[] = {
        45, 0,
        66, 1,
        0 };
+blk_t test5[] = { 31, 20, 17, 51, 23, 1, 56, 57, 0 };
+blk_t test5a[] = {
+       50, ADD_BLK,
+       51, DEL_BLK,
+       57, DEL_BLK,
+       66, ADD_BLK,
+       31, DEL_BLK,
+       12, ADD_BLK,
+       2, ADD_BLK,
+       13, ADD_BLK,
+       1, DEL_BLK,
+       0
+       };
+               
 
 static int test_fail = 0;
 
@@ -118,6 +135,38 @@ static void validate_test_seq(badblocks_list bb, blk_t *vec)
        }
 }
 
+static void do_test_seq(badblocks_list bb, blk_t *vec)
+{
+       int     i, match;
+
+       for (i = 0; vec[i]; i += 2) {
+               switch (vec[i+1]) {
+               case ADD_BLK:
+                       ext2fs_badblocks_list_add(bb, vec[i]);
+                       match = ext2fs_badblocks_list_test(bb, vec[i]);
+                       printf("Adding block %d --- now %s\n", vec[i], 
+                              match ? "present" : "absent");
+                       if (!match) {
+                               printf("FAILURE!\n");
+                               test_fail++;
+                       }
+                       break;
+               case DEL_BLK:
+                       ext2fs_badblocks_list_del(bb, vec[i]);
+                       match = ext2fs_badblocks_list_test(bb, vec[i]);
+                       printf("Removing block %d --- now %s\n", vec[i], 
+                              ext2fs_badblocks_list_test(bb, vec[i]) ? 
+                              "present" : "absent");
+                       if (match) {
+                               printf("FAILURE!\n");
+                               test_fail++;
+                       }
+                       break;
+               }
+       }
+}
+
+
 int file_test(badblocks_list bb)
 {
        badblocks_list new_bb = 0;
@@ -156,11 +205,11 @@ int file_test(badblocks_list bb)
 
 int main(int argc, char **argv)
 {
-       badblocks_list bb1, bb2, bb3, bb4;
+       badblocks_list bb1, bb2, bb3, bb4, bb5;
        int     equal;
        errcode_t       retval;
 
-       bb1 = bb2 = bb3 = bb4 = 0;
+       bb1 = bb2 = bb3 = bb4 = bb5 = 0;
 
        printf("test1: ");
        retval = create_test_list(test1, &bb1);
@@ -189,7 +238,19 @@ int main(int argc, char **argv)
        }
        printf("\n");
 
-       if (bb1 && bb2 && bb3 && bb4) {
+       printf("test5: ");
+       retval = create_test_list(test5, &bb5);
+       if (retval == 0) {
+               print_list(bb5, 0);
+               printf("\n");
+               do_test_seq(bb5, test5a);
+               printf("After test5 sequence: ");
+               print_list(bb5, 0);
+               printf("\n");
+       }
+       printf("\n");
+
+       if (bb1 && bb2 && bb3 && bb4 && bb5) {
                printf("Comparison tests:\n");
                equal = ext2fs_badblocks_equal(bb1, bb2);
                printf("bb1 and bb2 are %sequal.\n", equal ? "" : "NOT "); 
@@ -205,14 +266,19 @@ int main(int argc, char **argv)
                printf("bb1 and bb4 are %sequal.\n", equal ? "" : "NOT "); 
                if (equal)
                        test_fail++;
+
+               equal = ext2fs_badblocks_equal(bb4, bb5);
+               printf("bb4 and bb5 are %sequal.\n", equal ? "" : "NOT "); 
+               if (!equal)
+                       test_fail++;
                printf("\n");
        }
        
+       file_test(bb4);
+       
        if (test_fail == 0)
                printf("ext2fs library badblocks tests checks out OK!\n");
 
-       file_test(bb4);
-       
        if (bb1)
                ext2fs_badblocks_list_free(bb1);
        if (bb2)
index e7667c8..b059873 100644 (file)
@@ -1,3 +1,12 @@
+2003-06-24    <tytso@snap.thunk.org>
+
+       * resize2fs.c (block_mover): Don't move blocks associated with the
+               bad blocks inode.  Instead, just remove them from the
+               badblocks list.  (Note this means that shrinking and then
+               enlarging a filesystem is not a reversible operation;
+               information about bad blocks in the part of the filesystem
+               which is to be chopped off is discarded.)
+
 2003-06-08  Theodore Ts'o  <tytso@mit.edu>
 
        * resize2fs.8.in: Make explicit that you need to run resize2fs
index f9543cc..6f60cfc 100644 (file)
@@ -837,6 +837,12 @@ static errcode_t block_mover(ext2_resize_t rfs)
        errcode_t               retval;
        int                     size, c;
        int                     to_move, moved;
+       ext2_badblocks_list     badblock_list = 0;
+       int                     bb_modified = 0;
+       
+       retval = ext2fs_read_bb_inode(old_fs, &badblock_list);
+       if (retval)
+               return retval;
 
        new_blk = fs->super->s_first_data_block;
        if (!rfs->itable_buf) {
@@ -862,6 +868,11 @@ static errcode_t block_mover(ext2_resize_t rfs)
                        continue;
                if (!ext2fs_test_block_bitmap(rfs->move_blocks, blk))
                        continue;
+               if (ext2fs_badblocks_list_test(badblock_list, blk)) {
+                       ext2fs_badblocks_list_del(badblock_list, blk);
+                       bb_modified++;
+                       continue;
+               }
 
                new_blk = get_new_block(rfs);
                if (!new_blk) {
@@ -931,6 +942,12 @@ static errcode_t block_mover(ext2_resize_t rfs)
        }
 
 errout:
+       if (badblock_list) {
+               if (!retval && bb_modified)
+                       retval = ext2fs_update_bb_inode(old_fs,
+                                                       badblock_list);
+               ext2fs_badblocks_list_free(badblock_list);
+       }
        return retval;
 }