summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKen Sumrall <ksumrall@android.com>2011-06-22 18:34:28 -0700
committerKen Sumrall <ksumrall@android.com>2011-06-22 18:34:28 -0700
commit7e5ff13c55eb29748c07768bd7134819cbcbd4b0 (patch)
tree2b308ab9bd2e66a0372e34f92a43cfaef63dcf6e
parent97fc910ce0e05862888fd1d9e1938feba40f7539 (diff)
downloadextras-7e5ff13c55eb29748c07768bd7134819cbcbd4b0.tar.gz
Add test/debugging code to ext4fixup
Add debugging test code to specify where to bail partway through Add a script to drive the test code for automated testing. This found 4 bugs! Change-Id: I14dc8b1e2c9d2d2f332346958d488feaf768d396
-rw-r--r--ext4_utils/ext4fixup.c28
-rw-r--r--ext4_utils/ext4fixup.h3
-rw-r--r--ext4_utils/ext4fixup_main.c8
-rwxr-xr-xext4_utils/test_ext4fixup71
4 files changed, 105 insertions, 5 deletions
diff --git a/ext4_utils/ext4fixup.c b/ext4_utils/ext4fixup.c
index cb596371..5e04602a 100644
--- a/ext4_utils/ext4fixup.c
+++ b/ext4_utils/ext4fixup.c
@@ -56,6 +56,12 @@
#define STATE_UPDATING_INUMS 2
#define STATE_UPDATING_SB 3
+/* Used for automated testing of this programs ability to stop and be restarted wthout error */
+static int bail_phase = 0;
+static int bail_loc = 0;
+static int bail_count = 0;
+static int count = 0;
+
/* global flags */
static int verbose = 0;
static int no_write = 0;
@@ -432,6 +438,9 @@ static int update_superblocks_and_bg_desc(int fd, int state)
critical_error("failed to write all of block group descriptors");
}
}
+ if ((bail_phase == 4) && ((unsigned int)bail_count == i)) {
+ critical_error("bailing at phase 4\n");
+ }
}
return 0;
@@ -663,6 +672,7 @@ static int recurse_dir(int fd, struct ext4_inode *inode, char *dirbuf, int dirsi
dirp = (struct ext4_dir_entry_2 *)dirbuf;
while (dirp < (struct ext4_dir_entry_2 *)(dirbuf + dirsize)) {
+ count++;
leftover_space = (char *)(dirbuf + dirsize) - (char *)dirp;
if (((mode == SANITY_CHECK_PASS) || (mode == UPDATE_INODE_NUMS)) &&
(leftover_space <= 8) && prev_dirp) {
@@ -743,6 +753,10 @@ static int recurse_dir(int fd, struct ext4_inode *inode, char *dirbuf, int dirsi
}
}
+ if ((bail_phase == mode) && (bail_loc == 1) && (bail_count == count)) {
+ critical_error("Bailing at phase %d, loc 1 and count %d\n", mode, count);
+ }
+
/* Point dirp at the next entry */
prev_dirp = dirp;
dirp = (struct ext4_dir_entry_2*)((char *)dirp + dirp->rec_len);
@@ -751,6 +765,9 @@ static int recurse_dir(int fd, struct ext4_inode *inode, char *dirbuf, int dirsi
/* Write out all the blocks for this directory */
for (i = 0; i < num_blocks; i++) {
write_block(fd, block_list[i], dirbuf + (i * info.block_size));
+ if ((bail_phase == mode) && (bail_loc == 2) && (bail_count <= count)) {
+ critical_error("Bailing at phase %d, loc 2 and count %d\n", mode, count);
+ }
}
free(block_list);
@@ -760,10 +777,11 @@ static int recurse_dir(int fd, struct ext4_inode *inode, char *dirbuf, int dirsi
int ext4fixup(char *fsdev)
{
- return ext4fixup_internal(fsdev, 0, 0);
+ return ext4fixup_internal(fsdev, 0, 0, 0, 0, 0);
}
-int ext4fixup_internal(char *fsdev, int v_flag, int n_flag)
+int ext4fixup_internal(char *fsdev, int v_flag, int n_flag,
+ int stop_phase, int stop_loc, int stop_count)
{
int fd;
struct ext4_inode root_inode;
@@ -776,6 +794,10 @@ int ext4fixup_internal(char *fsdev, int v_flag, int n_flag)
verbose = v_flag;
no_write = n_flag;
+ bail_phase = stop_phase;
+ bail_loc = stop_loc;
+ bail_count = stop_count;
+
fd = open(fsdev, O_RDWR);
if (fd < 0)
@@ -845,12 +867,14 @@ int ext4fixup_internal(char *fsdev, int v_flag, int n_flag)
}
if (get_fs_fixup_state(fd) == STATE_MARKING_INUMS) {
+ count = 0; /* Reset debugging counter */
if (!recurse_dir(fd, &root_inode, dirbuf, dirsize, MARK_INODE_NUMS)) {
set_fs_fixup_state(fd, STATE_UPDATING_INUMS);
}
}
if (get_fs_fixup_state(fd) == STATE_UPDATING_INUMS) {
+ count = 0; /* Reset debugging counter */
if (!recurse_dir(fd, &root_inode, dirbuf, dirsize, UPDATE_INODE_NUMS)) {
set_fs_fixup_state(fd, STATE_UPDATING_SB);
}
diff --git a/ext4_utils/ext4fixup.h b/ext4_utils/ext4fixup.h
index 94395e7b..6ea21132 100644
--- a/ext4_utils/ext4fixup.h
+++ b/ext4_utils/ext4fixup.h
@@ -15,5 +15,6 @@
*/
int ext4fixup(char *fsdev);
-int ext4fixup_internal(char *fsdev, int v_flag, int n_flag);
+int ext4fixup_internal(char *fsdev, int v_flag, int n_flag,
+ int stop_phase, int stop_loc, int stop_count);
diff --git a/ext4_utils/ext4fixup_main.c b/ext4_utils/ext4fixup_main.c
index 8b069712..47c7e659 100644
--- a/ext4_utils/ext4fixup_main.c
+++ b/ext4_utils/ext4fixup_main.c
@@ -32,10 +32,11 @@ int main(int argc, char **argv)
int no_write = 0;
char *fsdev;
char *me;
+ int stop_phase = 0, stop_loc = 0, stop_count = 0;
me = basename(argv[0]);
- while ((opt = getopt(argc, argv, "vn")) != -1) {
+ while ((opt = getopt(argc, argv, "vnd:")) != -1) {
switch (opt) {
case 'v':
verbose = 1;
@@ -43,6 +44,9 @@ int main(int argc, char **argv)
case 'n':
no_write = 1;
break;
+ case 'd':
+ sscanf(optarg, "%d,%d,%d", &stop_phase, &stop_loc, &stop_count);
+ break;
}
}
@@ -60,5 +64,5 @@ int main(int argc, char **argv)
exit(EXIT_FAILURE);
}
- return ext4fixup_internal(fsdev, verbose, no_write);
+ return ext4fixup_internal(fsdev, verbose, no_write, stop_phase, stop_loc, stop_count);
}
diff --git a/ext4_utils/test_ext4fixup b/ext4_utils/test_ext4fixup
new file mode 100755
index 00000000..a920a59d
--- /dev/null
+++ b/ext4_utils/test_ext4fixup
@@ -0,0 +1,71 @@
+#!/bin/bash
+
+typeset -i I ITERATIONS PHASE LOC COUNT MAXCOUNT
+
+ME=`basename $0`
+
+if [ "$#" -ne 3 ]
+then
+ echo "$ME: Usage: $ME <iterations> <maxcount> <filesystem_image>" >&2
+ exit 1;
+fi
+
+ITERATIONS="$1"
+MAXCOUNT="$2"
+ORIG_FS_IMAGE="$3"
+FIXED_FS_IMAGE="/tmp/fixedfsimage.$$"
+NEW_FS_IMAGE="/tmp/newfsimage.$$"
+
+if [ ! -f "$ORIG_FS_IMAGE" ]
+then
+ echo "$ME: Filesystem image $NEW_FS_IMAGE does not exist" >&2
+ exit 1
+fi
+
+trap "rm -f $NEW_FS_IMAGE $FIXED_FS_IMAGE" 0 1 2 3 15
+
+rm -f "$NEW_FS_IMAGE" "$FIXED_FS_IMAGE"
+
+# Create the fixed image to compare against
+cp "$ORIG_FS_IMAGE" "$FIXED_FS_IMAGE"
+ext4fixup "$FIXED_FS_IMAGE"
+
+if [ "$?" -ne 0 ]
+then
+ echo "$ME: ext4fixup failed!\n"
+ exit 1
+fi
+
+I=0
+while [ "$I" -lt "$ITERATIONS" ]
+do
+ # There is also a phase 4, which is writing out the updated superblocks and
+ # block group descriptors. Test the with a separate script.
+ let PHASE="$RANDOM"%3 # 0 to 2
+ let PHASE++ # 1 to 3
+ let LOC="$RANDOM"%2 # 0 to 1
+ let LOC++ # 1 to 2
+ let COUNT="$RANDOM"%"$MAXCOUNT"
+
+ # Make a copy of the original image to fixup
+ cp "$ORIG_FS_IMAGE" "$NEW_FS_IMAGE"
+
+ # Run the fixup tool, but die partway through to see if we can recover
+ ext4fixup -d "$PHASE,$LOC,$COUNT" "$NEW_FS_IMAGE" 2>/dev/null
+
+ # run it again without -d to have it finish the job
+ ext4fixup "$NEW_FS_IMAGE"
+
+ if cmp "$FIXED_FS_IMAGE" "$NEW_FS_IMAGE"
+ then
+ :
+ else
+ echo "$ME: test failed with parameters $PHASE, $LOC, $COUNT"
+ exit 1
+ fi
+
+ rm -f "$NEW_FS_IMAGE"
+
+ let I++
+done
+