blob: 20cd42f0efe6f61481197e3bfdd946f05f1ee06d [file]
/*
* Copyright 2000-2004 by Hans Reiser, licensing governed by
* reiserfsprogs/README
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "debugreiserfs.h"
#include "misc/unaligned.h"
#include "util/print.h"
#include <time.h>
extern struct reiserfs_fsstat g_stat_info;
int do_one_ih_corrupt (reiserfs_ih_t * ih, unsigned int nr_bytes);
int do_one_ih_random_corrupt (reiserfs_ih_t * ih);
void do_one_corruption_in_one_block (reiserfs_filsys_t * fs, reiserfs_bh_t * bh, char * corruption_command);
int corrupt_block_header (reiserfs_node_head_t * blkh, unsigned int offset, unsigned int bytes );
void do_one_block_random_corrupt (reiserfs_bh_t * bh);
static int str2int (char * str, int * res)
{
int val;
char * tmp;
val = (int) strtol (str, &tmp, 0);
if (tmp == str)
/* could not convert string into a number */
return 0;
*res = val;
return 1;
}
static int get_rand (double min, double max) {
/* srand (time (0)); */
int ret;
ret = (int)(min + (int)((max - min + 1) * rand() / (RAND_MAX + 1.0)));
if ((ret < min) || (ret > max))
misc_die ("get_rand failed: min %d, max %d, returned %d\n", (int)min, (int)max, ret);
return ret;
}
static void edit_journal_params (reiserfs_journal_param_t * jp)
{
char str[256];
int num;
printf ("Journal parameters:\n");
printf ("\tDevice: current: %x: new:", reiserfs_jp_get_dev (jp));
fgets(str, sizeof(str), stdin);
if (str2int (str, &num))
reiserfs_jp_set_dev (jp, num);
printf ("\tFirst block: current: %d: new:",
reiserfs_jp_get_start (jp));
fgets(str, sizeof(str), stdin);
if (str2int (str, &num))
reiserfs_jp_set_start (jp, num);
printf ("\tSize: current: %d: new:", reiserfs_jp_get_size (jp));
fgets(str, sizeof(str), stdin);
if (str2int (str, &num))
reiserfs_jp_set_size (jp, num);
printf ("\tMagic number: current: %d: new:", reiserfs_jp_get_magic (jp));
fgets(str, sizeof(str), stdin);
if (str2int (str, &num))
reiserfs_jp_set_magic (jp, num);
printf ("\tMax transaction size: current: %d: new:",
reiserfs_jp_get_tlen (jp));
fgets(str, sizeof(str), stdin);
if (str2int (str, &num))
reiserfs_jp_set_tlen (jp, num);
printf ("\tMax batch size: current: %d: new:",
reiserfs_jp_get_max_batch (jp));
fgets(str, sizeof(str), stdin);
if (str2int (str, &num))
reiserfs_jp_set_max_batch (jp, num);
printf ("\tMax commit age: current: %d: new:",
reiserfs_jp_get_commit_age (jp));
fgets(str, sizeof(str), stdin);
if (str2int (str, &num))
reiserfs_jp_set_commit_age (jp, num);
}
/* this allows to edit all super block fields */
static void edit_super_block (reiserfs_filsys_t * fs)
{
char str[256];
int num;
/* bs_block_count */
printf ("\tBlock count: current: %u: new:",
reiserfs_sb_get_blocks (fs->fs_ondisk_sb));
fgets(str, sizeof(str), stdin);
if (str2int (str, &num))
reiserfs_sb_set_blocks (fs->fs_ondisk_sb, num);
/* sb_free_blocks */
printf ("\tFree block count: current: %u: new:",
reiserfs_sb_get_free (fs->fs_ondisk_sb));
fgets(str, sizeof(str), stdin);
if (str2int (str, &num))
reiserfs_sb_set_free (fs->fs_ondisk_sb, num);
/* sb_root_block */
printf ("\tRoot block: current: %u: new:",
reiserfs_sb_get_root (fs->fs_ondisk_sb));
fgets(str, sizeof(str), stdin);
if (str2int (str, &num))
reiserfs_sb_set_root (fs->fs_ondisk_sb, num);
/* sb_journal */
edit_journal_params (reiserfs_sb_jp (fs->fs_ondisk_sb));
/* sb_blocksize */
printf ("\tBlocksize: current: %u: new:",
reiserfs_sb_get_blksize (fs->fs_ondisk_sb));
fgets(str, sizeof(str), stdin);
if (str2int (str, &num))
reiserfs_sb_set_blksize (fs->fs_ondisk_sb, num);
/* sb_oid_maxsize */
printf ("\tMax objectid size: current: %u: new:",
reiserfs_sb_get_mapmax (fs->fs_ondisk_sb));
fgets(str, sizeof(str), stdin);
if (str2int (str, &num))
reiserfs_sb_set_mapmax (fs->fs_ondisk_sb, num);
/* sb_oid_cursize */
printf ("\tCur objectid size: current: %u: new:",
reiserfs_sb_get_mapcur (fs->fs_ondisk_sb));
fgets(str, sizeof(str), stdin);
if (str2int (str, &num))
reiserfs_sb_set_mapcur (fs->fs_ondisk_sb, num);
/* sb_state */
printf ("\tUmount state: current: %u: new:",
reiserfs_sb_get_umount (fs->fs_ondisk_sb));
fgets(str, sizeof(str), stdin);
if (str2int (str, &num))
reiserfs_sb_set_umount (fs->fs_ondisk_sb, num);
/* char s_magic [10]; */
printf ("\tMagic: current: \"%s\": new:", fs->fs_ondisk_sb->s_v1.s_magic);
fgets(str, sizeof(str), stdin);
if (strcmp (str, "\n"))
strncpy (fs->fs_ondisk_sb->s_v1.s_magic,
str, strlen(str) > 10 ? 10 : strlen(str));
/* __u16 sb_fsck_state; */
printf ("\tFielsystem state: current: %u: new:",
reiserfs_sb_get_state (fs->fs_ondisk_sb));
fgets(str, sizeof(str), stdin);
if (str2int (str, &num))
reiserfs_sb_set_state (fs->fs_ondisk_sb, num);
/* __u32 sb_hash_function_code; */
printf ("\tHash code: current: %u: new (tea %d, r5 %d, rupasov %d):",
reiserfs_sb_get_hash (fs->fs_ondisk_sb), REISERFS_HASH_TEA,
REISERFS_HASH_R5, REISERFS_HASH_YURA);
fgets(str, sizeof(str), stdin);
if (str2int (str, &num))
reiserfs_sb_set_hash (fs->fs_ondisk_sb, num);
/* __u16 sb_tree_height; */
printf ("\tTree height: current: %u: new:",
reiserfs_sb_get_height (fs->fs_ondisk_sb));
fgets(str, sizeof(str), stdin);
if (str2int (str, &num))
reiserfs_sb_set_height (fs->fs_ondisk_sb, num);
/* __u16 sb_bmap_nr; */
printf ("\tNumber of bitmaps: current: %u: new:",
reiserfs_sb_get_bmaps (fs->fs_ondisk_sb));
fgets(str, sizeof(str), stdin);
if (str2int (str, &num))
reiserfs_sb_set_bmaps (fs->fs_ondisk_sb, num);
/* __u16 sb_version; */
printf ("\tFilesystem format: current: %u: new:",
le16_to_cpu (fs->fs_ondisk_sb->s_v1.sb_version));
fgets(str, sizeof(str), stdin);
if (str2int (str, &num))
reiserfs_sb_set_version (fs->fs_ondisk_sb, num);
/* __u16 sb_reserved_for_journal; */
printf ("\tSpace reserved for journal: current: %u: new:",
reiserfs_sb_get_reserved (fs->fs_ondisk_sb));
fgets(str, sizeof(str), stdin);
if (str2int (str, &num))
reiserfs_sb_set_reserved (fs->fs_ondisk_sb, num);
reiserfs_node_print (stdout, fs, fs->fs_super_bh);
if (util_user_confirmed (stderr, "Is this ok ? [N/Yes]: ", "Yes\n")) {
reiserfs_buffer_mkdirty (fs->fs_super_bh);
reiserfs_buffer_write (fs->fs_super_bh);
}
}
static void corrupt_clobber_hash (char * name, reiserfs_ih_t * ih,
reiserfs_deh_t * deh)
{
printf ("\tCorrupting deh_offset of entry \"%s\" of [%u %u]\n", name,
reiserfs_key_get_did (&ih->ih_key), reiserfs_key_get_oid (&ih->ih_key));
reiserfs_deh_set_off (deh, 700);
}
/* this reads list of desired corruptions from stdin and perform the
corruptions. Format of that list:
A hash_code
C name objectid - 'C'ut entry 'name' from directory item with 'objectid'
H name objectid - clobber 'H'hash of entry 'name' of directory 'objectid'
I item_num pos_in_item make pos_in_item-th slot of extent item to point out of device
O item_num - destroy item 'O'rder - make 'item_num'-th to have key bigger than 'item_num' + 1-th item
D item_num - 'D'elete item_num-th item
S item_num value - change file size (item_num-th item must be stat data)
F item_num value - change sd_fdb of stat data
J item_num objectid
E name objectid new - change entry's deh_objectid to new
P - print the block
B offset bytes_to_corrupt - corrupt bytes_to_corrupt bytes in block header,
start from offset
*/
void do_corrupt_one_block (reiserfs_filsys_t * fs, char * fline)
{
reiserfs_bh_t * bh;
char line[256];
size_t n = 0;
unsigned long block;
block = certain_block (fs);
printf ("block = %lu\n", block);
if (block == fs->fs_super_bh->b_blocknr) {
edit_super_block (fs);
return;
}
if (!fs->fs_bitmap2) {
reiserfs_bh_t * bm_bh;
unsigned long bm_block;
if (reiserfs_bitmap_spread (fs))
bm_block = ( block / (fs->fs_blocksize * 8) ) ?
(block / (fs->fs_blocksize * 8)) * (fs->fs_blocksize * 8) :
fs->fs_super_bh->b_blocknr + 1;
else
bm_block = fs->fs_super_bh->b_blocknr + 1 + (block / (fs->fs_blocksize * 8));
bm_bh = reiserfs_buffer_read (fs->fs_dev, bm_block, fs->fs_blocksize);
if (bm_bh) {
if ( misc_test_bit((block % (fs->fs_blocksize * 8)), bm_bh->b_data) )
fprintf (stderr, "%lu is used in ondisk bitmap\n", block);
else
fprintf (stderr, "%lu is free in ondisk bitmap\n", block);
reiserfs_buffer_close (bm_bh);
}
} else {
if (reiserfs_bitmap_test_bit (fs->fs_bitmap2, block))
fprintf (stderr, "%lu is used in ondisk bitmap\n", block);
else
fprintf (stderr, "%lu is free in ondisk bitmap\n", block);
}
/* READ block */
bh = reiserfs_buffer_read (fs->fs_dev, block, fs->fs_blocksize);
if (!bh) {
printf ("corrupt_one_block: reiserfs_buffer_read fialed\n");
return;
}
if (reiserfs_node_type (bh) != NT_LEAF) {
printf ("Can not corrupt not a leaf node\n");
reiserfs_buffer_close (bh);
return;
}
printf ("Corrupting block %lu..\n", bh->b_blocknr);
if (data(fs)->log_file_name) {
printf ("Log file : %s\n", data(fs)->log_file_name);
} else {
printf ("No Log file specified\n");
}
if (fline != NULL) {
do_one_corruption_in_one_block (fs, bh, fline);
if ((data(fs)->log_file_name) && (data(fs)->log)) {
fprintf (data(fs)->log, "%lu\n", block);
fprintf (data(fs)->log, "%s\n", fline);
}
} else {
/* Get list of corruptions from stdin */
while (fgets(line, sizeof(line), stdin)) {
if ( line [0] == '\n' ) {
n = 0;
break;
}
do_one_corruption_in_one_block (fs, bh, line);
if ((data(fs)->log_file_name) && (data(fs)->log)) {
fprintf (data(fs)->log, "%lu\n", block);
fprintf (data(fs)->log, "%s\n", line);
}
line[0] = '\0';
n = 0;
}
}
printf ("Done\n");
reiserfs_buffer_write(bh);
reiserfs_buffer_close (bh);
return;
}
void do_one_corruption_in_one_block (reiserfs_filsys_t * fs,
reiserfs_bh_t * bh,
char * corruption_command)
{
int i, j;
reiserfs_ih_t * ih;
int item_num;
int item_numbers;
int bytes_to_corrupt;
char code, name [100];
__u32 objectid, new_objectid;
int value;
int hash_code;
unsigned int pos_in_item;
int type, format;
printf ("corruption_command : %s", corruption_command);
switch (corruption_command [0]) {
case '#':
case '\n':
break;
case '?':
printf ("A hash_code - reset hAsh code in super block\n"
"T item_num type (0, 1, 2, 3) format (0, 1)\n"
"C name objectid - Cut entry 'name' from directory item with 'objectid'\n"
"H name objectid - clobber Hash of entry 'name' of directory 'objectid'\n"
"I item_num pos_in_item make pos_in_tem-th slot of Indirect item to point out of device\n"
"O item_num - destroy item Order - make 'item_num'-th to have key bigger than 'item_num' + 1-th item\n"
"D item_num - Delete item_num-th item\n"
"S item_num value - change file Size (item_num-th item must be stat data)\n"
"F item_num value - change sd_First_direct_byte of stat data\n"
"J item_num objectid - set 'obJectid' of 'item_num'-th item\n"
"E name objectid objectid - set deh_objectid of an entry to objectid\n"
"N item_numbers bytes_to_corrupt - corrupt bytes_to_corrupt in number of bytes in item_numbers items\n"
"B offset bytes_to_corrupt - corrupt bytes_to_corrupt in block_header, start corruption from offset\n");
break;
case 'P':
reiserfs_node_print (stderr, fs, bh, 3, -1, -1);
break;
case 'A':
/* corrupt hash record in super block */
if (sscanf (corruption_command, "%c %d\n", &code, &hash_code) != 2) {
printf ("Wrong format \'%c\'\n", corruption_command [0]);
return;
}
reiserfs_warning (stderr, "Changing %s to %s\n",
reiserfs_hash_name (reiserfs_sb_get_hash (fs->fs_ondisk_sb)),
reiserfs_hash_name (hash_code));
reiserfs_sb_set_hash (fs->fs_ondisk_sb, hash_code);
break;
case 'C': /* cut entry */
case 'H': /* make hash wrong */
if (sscanf (corruption_command, "%c %s %u\n", &code, name, &objectid) != 3) {
printf ("Wrong format \'%c\'\n", corruption_command [0]);
return;
}
ih = reiserfs_ih_at (bh, 0);
for (i = 0; i < reiserfs_nh_get_items (NODE_HEAD (bh)); i ++, ih ++) {
reiserfs_deh_t * deh;
/* look for property objectid */
if (reiserfs_key_get_oid (&ih->ih_key) != objectid || !reiserfs_ih_dir (ih))
continue;
deh = reiserfs_deh (bh, ih);
for (j = 0; j < reiserfs_ih_get_entries (ih); j ++, deh ++) {
/* look for proper entry */
if (reiserfs_direntry_name_len (ih, deh, j) == (int)strlen (name) &&
!strncmp (name, reiserfs_deh_name (deh, j), strlen (name)))
break;
}
if (j == reiserfs_ih_get_entries (ih)) {
printf ("Can't find entry %s\n", name);
exit (1);
}
switch (code) {
case 'H' : /* clobber hash */
corrupt_clobber_hash (name, ih, deh);
break;
case 'C' : /* cut entry */
reiserfs_leaf_delete_entry (fs, bh, i, j, 1);
break;
default:
printf ("Unknown command found\n");
}
}
if (!REISERFS_NODE_INTREE (bh)) {
printf ("NOTE: block is deleted from the tree\n");
exit (0);
}
break;
case 'E': /* set objectid : used to simulate objectid sharing problem */
if (sscanf (corruption_command, "%c %s %u %d\n", &code, name, &objectid, &new_objectid) != 4) {
printf ("Wrong format \'%c\'\n", corruption_command [0]);
return;
}
ih = reiserfs_ih_at (bh, 0);
for (i = 0; i < reiserfs_nh_get_items (NODE_HEAD (bh)); i ++, ih ++) {
reiserfs_deh_t * deh;
/* look for property objectid */
if (reiserfs_key_get_oid (&ih->ih_key) != objectid || !reiserfs_ih_dir (ih))
continue;
deh = reiserfs_deh (bh, ih);
reiserfs_deh_set_obid (deh, new_objectid);
break;
}
break;
case 'T': /* set type of item */
if (sscanf (corruption_command, "%c %d %d %d\n", &code, &item_num, &type, &format) != 4) {
printf ("Wrong format \'%c\'\n", corruption_command [0]);
return;
}
if (item_num > reiserfs_nh_get_items (NODE_HEAD (bh))) {
printf ("Wrong format \'%c\', wrong item_num \n", corruption_command [0]);
return;
}
ih = reiserfs_ih_at (bh, item_num);
reiserfs_ih_set_format (ih, format);
reiserfs_key_set_type (format, &ih->ih_key, type);
break;
case 'J': /* set objectid : used to simulate objectid sharing problem */
if (sscanf (corruption_command, "%c %d %d\n", &code,
&item_num, &objectid) != 3)
{
printf ("Wrong format \'%c\'\n",
corruption_command [0]);
return;
}
if (item_num > reiserfs_nh_get_items (NODE_HEAD (bh))) {
printf ("Wrong format \'%c\', wrong item_num \n",
corruption_command [0]);
return;
}
ih = reiserfs_ih_at (bh, item_num);
reiserfs_key_set_oid (&ih->ih_key, objectid);
break;
case 'I': /* break unformatted node pointer */
if (sscanf (corruption_command, "%c %d %u\n", &code,
&item_num, &pos_in_item) != 3)
{
printf ("Wrong format \'%c\'\n",
corruption_command [0]);
return;
}
if (item_num > reiserfs_nh_get_items (NODE_HEAD (bh))) {
printf ("Wrong format \'%c\', wrong item_num \n",
corruption_command [0]);
return;
}
ih = reiserfs_ih_at (bh, item_num);
if (!reiserfs_ih_ext (ih) || pos_in_item >= reiserfs_ext_count (ih)) {
reiserfs_warning (stderr, "Not an extent item or there is "
"not so many unfm ptrs in it\n");
return;
}
d32_put((__u32 *)reiserfs_item_by_ih (bh, ih), pos_in_item,
reiserfs_sb_get_blocks (fs->fs_ondisk_sb) + 100);
break;
case 'D': /* delete item */
if (sscanf (corruption_command, "%c %d\n", &code, &item_num) != 2)
{
printf ("Wrong format \'%c\'\n",
corruption_command [0]);
return;
}
if (item_num > reiserfs_nh_get_items (NODE_HEAD (bh))) {
printf ("Wrong format \'%c\', wrong item_num \n",
corruption_command [0]);
return;
}
reiserfs_leaf_delete_item (fs, bh, item_num);
break;
case 'O': /* make item out of order */
{
reiserfs_key_t * key;
if (sscanf (corruption_command, "%c %d\n", &code,
&item_num) != 2)
{
printf ("Wrong format \'%c\'\n",
corruption_command [0]);
return;
}
if (item_num > reiserfs_nh_get_items (NODE_HEAD (bh))) {
printf ("Wrong format \'%c\', wrong item_num "
"\n", corruption_command [0]);
return;
}
/* destroy item order */
if (item_num == reiserfs_nh_get_items (NODE_HEAD (bh)) - 1)
{
printf ("can not destroy order\n");
return;
}
ih = reiserfs_ih_at (bh, item_num);
key = &(ih + 1)->ih_key;
reiserfs_key_set_did (&ih->ih_key, reiserfs_key_get_did (key) + 1);
break;
}
case 'S': /* corrupt st_size */
{
/* fixme: old stat data only */
reiserfs_sd_v1_t * sd;
if (sscanf (corruption_command, "%c %d %d\n",
&code, &item_num, &value) != 3)
{
printf ("Wrong format \'%c\'\n",
corruption_command [0]);
return;
}
if (item_num > reiserfs_nh_get_items (NODE_HEAD (bh))) {
printf ("Wrong format \'%c\', wrong item_num "
"\n", corruption_command [0]);
return;
}
ih = reiserfs_ih_at (bh, item_num);
sd = (reiserfs_sd_v1_t *)reiserfs_item_by_ih (bh, ih);
reiserfs_warning (stderr, "Changing sd_size of %k "
"from %d to %d\n", &ih->ih_key,
reiserfs_sd_v1_size(sd), value);
reiserfs_set_sd_v1_size( sd, value );
break;
}
case 'F': /* st_fdb */
{
/* fixme: old stat data only */
reiserfs_sd_v1_t * sd;
if (sscanf (corruption_command, "%c %d %d\n",
&code, &item_num, &value) != 3)
{
printf ("Wrong format \'%c\'\n",
corruption_command [0]);
return;
}
if (item_num > reiserfs_nh_get_items (NODE_HEAD (bh))) {
printf ("Wrong format \'%c\', wrong item_num "
"\n", corruption_command [0]);
return;
}
ih = reiserfs_ih_at (bh, item_num);
sd = (reiserfs_sd_v1_t *)reiserfs_item_by_ih (bh, ih);
reiserfs_warning (stderr, "Changing "
"sd_fdb of %k from "
"%d to %d\n", &ih->ih_key,
reiserfs_sd_v1_fdb(sd), value);
reiserfs_set_sd_v1_fdb( sd, value );
break;
}
case 'N': /* corrupt N number of items */
if (sscanf (corruption_command, "%c %d %d\n",
&code, &item_numbers, &bytes_to_corrupt) != 3)
{
printf ("Wrong format \'%c\'\n", corruption_command [0]);
return;
}
if (item_numbers > reiserfs_nh_get_items (NODE_HEAD (bh))) {
printf ("Wrong item_numbers %d expected not more then %d\n",
item_numbers, reiserfs_nh_get_items (NODE_HEAD (bh)));
return;
}
for (i = 0; i < item_numbers; i++) {
printf ("Do corruptions : %d item header; \n", i );
ih = reiserfs_ih_at (bh, i);
do_one_ih_corrupt (ih, bytes_to_corrupt);
printf ("Ok\n");
}
break;
case 'B' :
{
reiserfs_node_head_t * blkh;
unsigned int offset;
if (sscanf (corruption_command, "%c %d %d\n",
&code, &offset, &bytes_to_corrupt) != 3)
{
printf ("Wrong format \'%c\'\n", corruption_command [0]);
return;
}
blkh = NODE_HEAD (bh);
corrupt_block_header (blkh, offset, bytes_to_corrupt);
break;
}
default:
printf ("Unknown command found\n");
}
reiserfs_buffer_mkdirty (bh);
return;
}
/* corrupt first nr_bytes bytes in item header */
int do_one_ih_corrupt (reiserfs_ih_t * ih, unsigned int nr_bytes)
{
if (nr_bytes > REISERFS_IH_SIZE) {
printf ("Bad byte number %u expected not more then %lu\n",
nr_bytes, (unsigned long)REISERFS_IH_SIZE);
exit (1);
}
if (memset ((char *)ih, 0, nr_bytes) != ih ) {
perror ("do_one_ih_corrupt: memset failed");
exit (1);
}
if ((data(fs)->log_file_name) && (data(fs)->log))
fprintf (data(fs)->log, "\tfirst %u bytes corrupted\n",
nr_bytes);
printf ("\tfirst %u bytes corrupted\n", nr_bytes);
return 0;
}
/* item header random corruption */
int do_one_ih_random_corrupt (reiserfs_ih_t * ih)
{
unsigned int i;
unsigned int from;
unsigned int count;
from = get_rand (0, REISERFS_IH_SIZE - 1);
count = get_rand (1, REISERFS_IH_SIZE);
if (from + count > REISERFS_IH_SIZE)
count = REISERFS_IH_SIZE - from;
for (i = from; i < from + count; i ++)
((char *)ih)[i] = get_rand(0, 255);
if ((data(fs)->log_file_name) && (data(fs)->log))
fprintf (data(fs)->log, "\tfrom %u ( %u )\n", from, count);
printf ("\tfrom %u ( %u )\n", from, count);
return 0;
}
/* Corrupt n bytes in block header */
int corrupt_block_header (reiserfs_node_head_t * blkh, unsigned int offset,
unsigned int bytes)
{
if ((offset + bytes) > REISERFS_NODEH_SIZE) {
printf ("Bad offset number: %u or bad bytes number: %u, "
"the suumary value expected not more then %lu\n",
offset, bytes, (unsigned long)REISERFS_NODEH_SIZE);
exit (1);
}
if (memset ((char *)blkh, 0, bytes) != blkh ) {
perror ("corrupt_block_head: memset failed");
exit (1);
}
printf ("offset : %u, corrupt %u bytes\n", offset, bytes);
return 0;
}
/* corrupt random number of bytes within block header started from random
offset */
void do_one_blkh_random_corrupt (reiserfs_bh_t * bh)
{
reiserfs_node_head_t * blkh;
unsigned int from;
unsigned int count;
unsigned int i;
from = get_rand (0, REISERFS_NODEH_SIZE - 1);
count = get_rand (1, REISERFS_NODEH_SIZE);
blkh = NODE_HEAD (bh);
if (from + count > REISERFS_NODEH_SIZE)
count = REISERFS_NODEH_SIZE - from;
for (i = from; i < from + count; i ++)
((char *)blkh)[i] = get_rand(0, 255);
if ((data(fs)->log_file_name) && (data(fs)->log)) {
fprintf (data(fs)->log, "# : %lu # ", bh->b_blocknr);
fprintf (data(fs)->log, "from %u (%u)\n", from, count);
}
printf ("# : %lu # ", bh->b_blocknr);
printf ("from %u (%u)\n", from, count);
}
void do_leaves_corruption (reiserfs_filsys_t * fs,
unsigned long nr_leaves_cr)
{
reiserfs_bh_t * bh;
unsigned long nr_leaves = 0;
unsigned int i, should_be_corrupted;
srand (time (0));
printf ("%lu leaves will be corrupted\n", nr_leaves_cr);
if ((data(fs)->log_file_name) && (data(fs)->log)) {
fprintf (data(fs)->log, "Block headers in %lu leaves "
"will be corrupted\n", nr_leaves_cr);
}
if (reiserfs_bitmap_open (fs) < 0)
reiserfs_exit (1, "Could not open ondisk bitmap");
for (i = 0; (i < reiserfs_sb_get_blocks (fs->fs_ondisk_sb)) &&
nr_leaves < nr_leaves_cr; i ++) {
if (!reiserfs_bitmap_test_bit (fs->fs_bitmap2, i))
continue;
bh = reiserfs_buffer_read (fs->fs_dev, i, fs->fs_blocksize);
if (!bh) {
reiserfs_warning (stderr, "could not read "
"block %lu\n", i);
continue;
}
if (reiserfs_node_type (bh) != NT_LEAF) {
reiserfs_buffer_close (bh);
continue;
}
if ((!reiserfs_leaf_head (bh)) ||
(reiserfs_journal_block (fs, i)))
{
reiserfs_buffer_close (bh);
continue;
}
should_be_corrupted =
(unsigned int)get_rand ((double)0, (double)1);
if (should_be_corrupted == 0)
{
reiserfs_buffer_close (bh);
continue;
}
do_one_blkh_random_corrupt (bh);
/* do_one_block_random_corrupt (bh); */
reiserfs_buffer_mkdirty (bh);
reiserfs_buffer_write(bh);
reiserfs_buffer_close (bh);
nr_leaves ++;
}
if ((data(fs)->log_file_name) && (data(fs)->log)) {
fprintf (data(fs)->log, "%lu leaves WERE corrupted\n",
nr_leaves);
}
printf ("%lu leaves WERE corrupted\n", nr_leaves);
reiserfs_bitmap_close (fs);
return;
}
void do_one_block_random_corrupt (reiserfs_bh_t * bh)
{
unsigned int from = get_rand (0, bh->b_size - 1);
unsigned int count = get_rand (1, bh->b_size);
unsigned int i;
if (from + count > bh->b_size)
count = bh->b_size - from;
for (i = from; i < from + count; i ++)
((char *)bh->b_data)[i] = get_rand(0, 255);
if ((data(fs)->log_file_name) && (data(fs)->log)) {
fprintf (data(fs)->log, "# block %lu: ", bh->b_blocknr);
fprintf (data(fs)->log, "from %u ( %u )\n", from, count);
}
printf ("# block %lu: ", bh->b_blocknr);
printf ("from %u ( %u )\n", from, count);
}
void do_bitmap_corruption (reiserfs_filsys_t * fs)
{
unsigned long first = fs->fs_super_bh->b_blocknr + 1;
unsigned long nr_bitmap_to_corrupt;
unsigned long block, bmap_nr;;
reiserfs_bh_t * bh;
unsigned int i;
bmap_nr = reiserfs_bmap_nr(
reiserfs_sb_get_blocks(fs->fs_ondisk_sb),
fs->fs_blocksize);
nr_bitmap_to_corrupt = (unsigned long)get_rand (1, bmap_nr - 1);
if ((data(fs)->log_file_name) && (data(fs)->log)) {
fprintf (data(fs)->log, "%lu bitmaps will be "
"corrupted\n", nr_bitmap_to_corrupt);
}
printf ("%lu bitmaps will be corrupted\n", nr_bitmap_to_corrupt);
for (i = 0; i < nr_bitmap_to_corrupt; i ++ ) {
block = ( i == 0 ) ? first : fs->fs_blocksize * 8 * i;
bh = reiserfs_buffer_read (fs->fs_dev, block, fs->fs_blocksize);
if (!bh) {
printf ("do_bitmap_corruption: reiserfs_buffer_read "
"failed for bitmap %d: %lu\n", i, block);
exit (1);
}
do_one_block_random_corrupt (bh);
reiserfs_buffer_mkdirty (bh);
reiserfs_buffer_write(bh);
reiserfs_buffer_close (bh);
}
}
/* corrupt the random number of item headers in random number of leaves */
void do_ih_random_corrupt (reiserfs_filsys_t * fs, unsigned long nr_leaves_cr)
{
unsigned int nr_ih_cr;
unsigned int i, j;
reiserfs_bh_t * bh;
reiserfs_ih_t * ih;
unsigned long nr_leaves = 0;
unsigned int should_be_corrupted = 0;
srand (time (0));
printf ("item headers in %lu leaves will be corrupted\n",
nr_leaves_cr);
if ((data(fs)->log_file_name) && (data(fs)->log)) {
fprintf (data(fs)->log, "item headers in %lu leaves will "
"be corrupted\n", nr_leaves_cr);
}
if (reiserfs_bitmap_open (fs) < 0)
reiserfs_exit (1, "Could not open ondisk bitmap");
for (i = 0; (i < reiserfs_sb_get_blocks (fs->fs_ondisk_sb)) &&
nr_leaves < nr_leaves_cr; i ++) {
if (!reiserfs_bitmap_test_bit (fs->fs_bitmap2, i))
continue;
bh = reiserfs_buffer_read (fs->fs_dev, i, fs->fs_blocksize);
if (!bh) {
reiserfs_warning (stderr, "could not read "
"block %lu\n", i);
continue;
}
if (reiserfs_node_type (bh) != NT_LEAF) {
reiserfs_buffer_close (bh);
continue;
}
if ((!reiserfs_leaf_head (bh)) ||
(reiserfs_journal_block (fs, i)))
{
reiserfs_buffer_close (bh);
continue;
}
should_be_corrupted =
(unsigned int) get_rand ((double)0, (double)1);
if (should_be_corrupted == 0) {
reiserfs_buffer_close (bh);
continue;
}
nr_ih_cr = get_rand (1, reiserfs_nh_get_items (NODE_HEAD (bh)));
for (j = 0; j < nr_ih_cr; j ++ ) {
should_be_corrupted =
(unsigned int) get_rand ((double)0, (double)1);
if (should_be_corrupted == 0)
continue;
if ((data(fs)->log_file_name) && (data(fs)->log))
fprintf (data(fs)->log, "# block %lu , "
"item header %d\n", bh->b_blocknr, j);
printf ("# block %lu , item header %d\n",
bh->b_blocknr, j);
ih = reiserfs_ih_at (bh, j);
do_one_ih_random_corrupt (ih);
}
reiserfs_buffer_mkdirty (bh);
reiserfs_buffer_write(bh);
reiserfs_buffer_close (bh);
nr_leaves ++ ;
}
if ((data(fs)->log_file_name) && (data(fs)->log))
fprintf (data(fs)->log, "item headers in %lu leaves "
"WERE corrupted\n", nr_leaves);
printf ("item headers in %lu leaves WERE corrupted\n", nr_leaves);
reiserfs_bitmap_close (fs);
}
/* corrupt item */
void do_one_item_random_corrupt (reiserfs_bh_t * bh,
reiserfs_ih_t * ih)
{
unsigned int i;
unsigned int from;
unsigned int count;
char * p;
p = (char *)reiserfs_item_by_ih(bh, ih);
from = get_rand (0, reiserfs_ih_get_len(ih) - 1);
count = get_rand (1, reiserfs_ih_get_len(ih));
if (from + count > reiserfs_ih_get_len(ih))
count = reiserfs_ih_get_len(ih) - from;
for (i = from; i < from + count; i ++)
((char *)p)[i] = get_rand(0, 255);
if ((data(fs)->log_file_name) && (data(fs)->log))
fprintf (data(fs)->log, "item body \tfrom %u ( %u )\n",
from, count);
printf ("item body \tfrom %u ( %u )\n", from, count);
return ;
}
/* corrupt the random number of directory items in random number of leaves */
void do_dir_random_corrupt (reiserfs_filsys_t * fs,
unsigned long nr_leaves_cr)
{
unsigned int nr_ih_cr;
unsigned int i, j;
reiserfs_bh_t * bh;
reiserfs_ih_t * ih;
unsigned long nr_leaves = 0;
unsigned int should_be_corrupted = 0;
srand (time (0));
printf ("DIR items in %lu leaves will be corrupted\n", nr_leaves_cr);
if ((data(fs)->log_file_name) && (data(fs)->log)) {
fprintf (data(fs)->log, "DIR items in %lu leaves "
"will be corrupted\n", nr_leaves_cr);
}
if (reiserfs_bitmap_open (fs) < 0)
reiserfs_exit (1, "Could not open ondisk bitmap");
for (i = 0; (i < reiserfs_sb_get_blocks (fs->fs_ondisk_sb)) &&
nr_leaves < nr_leaves_cr; i ++) {
if (!reiserfs_bitmap_test_bit (fs->fs_bitmap2, i))
continue;
bh = reiserfs_buffer_read (fs->fs_dev, i, fs->fs_blocksize);
if (!bh) {
reiserfs_warning (stderr, "could not read "
"block %lu\n", i);
continue;
}
if (reiserfs_node_type (bh) != NT_LEAF) {
reiserfs_buffer_close (bh);
continue;
}
if ((!reiserfs_leaf_head (bh)) ||
(reiserfs_journal_block (fs, i)))
{
reiserfs_buffer_close (bh);
continue;
}
should_be_corrupted =
(unsigned int) get_rand ((double)0, (double)1);
if (should_be_corrupted == 0) {
reiserfs_buffer_close (bh);
continue;
}
/* get next item, look is it a DIR */
nr_ih_cr = get_rand (1, reiserfs_nh_get_items (NODE_HEAD (bh)));
for (j = 0; j < nr_ih_cr; j ++ ) {
should_be_corrupted =
(unsigned int) get_rand ((double)0, (double)1);
if (should_be_corrupted == 0)
continue;
if ((data(fs)->log_file_name) && (data(fs)->log))
fprintf (data(fs)->log, "# block %lu , item "
"%d\n", bh->b_blocknr, j);
printf ("# block %lu , item %d\n", bh->b_blocknr, j);
ih = reiserfs_ih_at (bh, j);
if (reiserfs_key_get_type (&ih->ih_key) !=
TYPE_DIRENTRY)
{
continue;
}
do_one_item_random_corrupt (bh, ih);
}
reiserfs_buffer_mkdirty (bh);
reiserfs_buffer_write(bh);
reiserfs_buffer_close (bh);
nr_leaves ++ ;
}
if ((data(fs)->log_file_name) && (data(fs)->log))
fprintf (data(fs)->log, "DIR items in %lu leaves WERE "
"corrupted\n", nr_leaves);
printf ("DIR items in %lu leaves WERE corrupted\n", nr_leaves);
reiserfs_bitmap_close (fs);
}
/* corrupt the random number of stat data items in random number of leaves */
void do_sd_random_corrupt (reiserfs_filsys_t * fs,
unsigned long nr_leaves_cr)
{
unsigned int nr_ih_cr;
unsigned int i, j;
reiserfs_bh_t * bh;
reiserfs_ih_t * ih;
unsigned long nr_leaves = 0;
unsigned int should_be_corrupted = 0;
srand (time (0));
printf ("SD items in %lu leaves will be corrupted\n", nr_leaves_cr);
if ((data(fs)->log_file_name) && (data(fs)->log)) {
fprintf (data(fs)->log, "SD items in %lu leaves will "
"be corrupted\n", nr_leaves_cr);
}
if (reiserfs_bitmap_open (fs) < 0)
reiserfs_exit (1, "Could not open ondisk bitmap");
for (i = 0; (i < reiserfs_sb_get_blocks (fs->fs_ondisk_sb)) &&
nr_leaves < nr_leaves_cr; i ++) {
if (!reiserfs_bitmap_test_bit (fs->fs_bitmap2, i))
continue;
bh = reiserfs_buffer_read (fs->fs_dev, i, fs->fs_blocksize);
if (!bh) {
reiserfs_warning (stderr, "could not read block %lu\n", i);
continue;
}
if (reiserfs_node_type (bh) != NT_LEAF) {
reiserfs_buffer_close (bh);
continue;
}
if ((!reiserfs_leaf_head (bh)) ||
(reiserfs_journal_block (fs, i)))
{
reiserfs_buffer_close (bh);
continue;
}
should_be_corrupted =
(unsigned int) get_rand ((double)0, (double)1);
if (should_be_corrupted == 0) {
reiserfs_buffer_close (bh);
continue;
}
/* get next item, look is it a SD */
nr_ih_cr = get_rand (1, reiserfs_nh_get_items (NODE_HEAD (bh)));
for (j = 0; j < nr_ih_cr; j ++ ) {
should_be_corrupted =
(unsigned int) get_rand ((double)0, (double)1);
if (should_be_corrupted == 0)
continue;
if ((data(fs)->log_file_name) && (data(fs)->log))
fprintf (data(fs)->log, "# block %lu , item "
"%d\n", bh->b_blocknr, j);
printf ("# block %lu , item %d\n", bh->b_blocknr, j);
ih = reiserfs_ih_at (bh, j);
if (reiserfs_key_get_type (&ih->ih_key) !=
TYPE_STAT_DATA)
{
continue;
}
do_one_item_random_corrupt (bh, ih);
}
reiserfs_buffer_mkdirty (bh);
reiserfs_buffer_write(bh);
reiserfs_buffer_close (bh);
nr_leaves ++ ;
}
if ((data(fs)->log_file_name) && (data(fs)->log))
fprintf (data(fs)->log, "SD items in %lu leaves "
"WERE corrupted\n", nr_leaves);
printf ("SD items in %lu leaves WERE corrupted\n", nr_leaves);
reiserfs_bitmap_close (fs);
}
/* corrupt the random number of indirect items in random number of leaves */
void do_ext_random_corrupt (reiserfs_filsys_t * fs,
unsigned long nr_leaves_cr)
{
unsigned int nr_ih_cr;
unsigned int i, j;
reiserfs_bh_t * bh;
reiserfs_ih_t * ih;
unsigned long nr_leaves = 0;
unsigned int should_be_corrupted = 0;
srand (time (0));
printf ("EXT items in %lu leaves will be corrupted\n", nr_leaves_cr);
if ((data(fs)->log_file_name) && (data(fs)->log)) {
fprintf (data(fs)->log, "EXT items in %lu leaves will "
"be corrupted\n", nr_leaves_cr);
}
if (reiserfs_bitmap_open (fs) < 0)
reiserfs_exit (1, "Could not open ondisk bitmap");
for (i = 0; (i < reiserfs_sb_get_blocks (fs->fs_ondisk_sb)) &&
nr_leaves < nr_leaves_cr; i ++) {
if (!reiserfs_bitmap_test_bit (fs->fs_bitmap2, i))
continue;
bh = reiserfs_buffer_read (fs->fs_dev, i, fs->fs_blocksize);
if (!bh) {
reiserfs_warning (stderr, "could not read "
"block %lu\n", i);
continue;
}
if (reiserfs_node_type (bh) != NT_LEAF) {
reiserfs_buffer_close (bh);
continue;
}
if ((!reiserfs_leaf_head (bh)) ||
(reiserfs_journal_block (fs, i)))
{
reiserfs_buffer_close (bh);
continue;
}
should_be_corrupted =
(unsigned int) get_rand ((double)0, (double)1);
if (should_be_corrupted == 0)
{
reiserfs_buffer_close (bh);
continue;
}
/* get next item, look is it an EXT */
nr_ih_cr = get_rand (1, reiserfs_nh_get_items (NODE_HEAD (bh)));
for (j = 0; j < nr_ih_cr; j ++ ) {
should_be_corrupted =
(unsigned int) get_rand ((double)0, (double)1);
if (should_be_corrupted == 0)
continue;
ih = reiserfs_ih_at (bh, j);
if (reiserfs_key_get_type (&ih->ih_key) !=
TYPE_EXTENT)
{
continue;
}
if ((data(fs)->log_file_name) && (data(fs)->log))
fprintf (data(fs)->log, "# block %lu , item "
"%d\n", bh->b_blocknr, j);
printf ("# block %lu , item %d\n", bh->b_blocknr, j);
do_one_item_random_corrupt (bh, ih);
}
reiserfs_buffer_mkdirty (bh);
reiserfs_buffer_write(bh);
reiserfs_buffer_close (bh);
nr_leaves ++ ;
}
if ((data(fs)->log_file_name) && (data(fs)->log))
fprintf (data(fs)->log, "EXT items in %lu leaves "
"WERE corrupted\n", nr_leaves);
printf ("EXT items in %lu leaves WERE corrupted\n", nr_leaves);
reiserfs_bitmap_close (fs);
}
/* this reads list of desired corruptions from stdin and performs the
corruptions. Format of that list:
B - the random number of bitmap to be corrupted
L nr_leaves - block headers in nr_leaves leaves to be corupted
H nr_leaves - the random number of item headers in nr_leaves to be corrupted
S nr_leaves - the random number of stat data items in nr_leaves to be
corrupted
D nr_leaves - the random number of directory items in nr_leaves to be
corrupted
I nr_leaves - the random number of extent items in nr_leaves to be
corrupted
*/
void what_to_corrupt (reiserfs_filsys_t * fs, char * corruption_command)
{
unsigned long nr_leaves_cr;
char code;
switch (corruption_command [0]){
case 'B' :
/* bitmap */
do_bitmap_corruption (fs);
break;
case 'L' :
/* leaves */
if (sscanf (corruption_command, "%c %lu\n",
&code, &nr_leaves_cr) != 2)
{
printf ("Wrong format \'%c\'\n", corruption_command [0]);
return;
}
do_leaves_corruption (fs, nr_leaves_cr);
break;
case 'H' :
/* item headers */
if (sscanf (corruption_command, "%c %lu\n",
&code, &nr_leaves_cr) != 2)
{
printf ("Wrong format \'%c\'\n", corruption_command [0]);
return;
}
do_ih_random_corrupt (fs, nr_leaves_cr);
break;
case 'D' :
/* directory items */
if (sscanf (corruption_command, "%c %lu\n",
&code, &nr_leaves_cr) != 2)
{
printf ("Wrong format \'%c\'\n", corruption_command [0]);
return;
}
do_dir_random_corrupt (fs, nr_leaves_cr);
break;
case 'S' :
/* stat data items */
if (sscanf (corruption_command, "%c %lu\n",
&code, &nr_leaves_cr) != 2)
{
printf ("Wrong format \'%c\'\n", corruption_command [0]);
return;
}
do_sd_random_corrupt (fs, nr_leaves_cr);
break;
case 'I' :
/* extent items */
if (sscanf (corruption_command, "%c %lu\n",
&code, &nr_leaves_cr) != 2)
{
printf ("Wrong format \'%c\'\n", corruption_command [0]);
return;
}
do_ext_random_corrupt (fs, nr_leaves_cr);
break;
default :
printf ("Unknown command specified\n");
}
}
void do_fs_random_corrupt (reiserfs_filsys_t * fs)
{
char line[256];
size_t n = 0;
printf ("Corrupting fs. Please insert one of the following command\n"
" B - the random number of bitmap to be corrupted\n"
" L nr_leaves - block headers in nr_leaves leaves to be corupted\n"
" H nr_leaves - the random number of item headers in nr_leaves to be corrupted\n"
" S nr_leaves - the random number of stat data items in nr_leaves to be corrupted\n"
" D nr_leaves - the random number of directory items in nr_leaves to be corrupted\n"
" I nr_leaves - the random number of extent items in nr_leaves to be corrupted\n"
".. ->\n");
/* Get list of corruptions from stdin */
while (fgets(line, sizeof(line), stdin)) {
if ( line [0] == '\n' ) {
n = 0;
break;
}
printf ("################## command : %s", line);
if ((data(fs)->log_file_name) && (data(fs)->log)) {
fprintf (data(fs)->log, "################## command : %s", line);
}
what_to_corrupt (fs, line);
line[0] = '\0';
n = 0;
}
}
/*
Local variables:
c-indentation-style: "K&R"
mode-name: "LC"
c-basic-offset: 4
tab-width: 4
fill-column: 80
End:
*/