diff -uNr linux-2.4.22.orig/fs/Config.in linux-2.4.22/fs/Config.in
--- linux-2.4.22.orig/fs/Config.in	2003-10-02 18:37:44.000000000 +0400
+++ linux-2.4.22/fs/Config.in	2003-10-02 18:51:04.000000000 +0400
@@ -13,6 +13,7 @@
 tristate 'Reiserfs support' CONFIG_REISERFS_FS
 dep_mbool '  Enable reiserfs debug mode' CONFIG_REISERFS_CHECK $CONFIG_REISERFS_FS
 dep_mbool '  Stats in /proc/fs/reiserfs' CONFIG_REISERFS_PROC_INFO $CONFIG_REISERFS_FS
+dep_mbool '  Allow badblock marking on live fs' CONFIG_REISERFS_BADBLOCKS $CONFIG_REISERFS_FS
 
 dep_tristate 'ADFS file system support (EXPERIMENTAL)' CONFIG_ADFS_FS $CONFIG_EXPERIMENTAL
 dep_mbool '  ADFS write support (DANGEROUS)' CONFIG_ADFS_FS_RW $CONFIG_ADFS_FS $CONFIG_EXPERIMENTAL
diff -uNr linux-2.4.22.orig/fs/reiserfs/Makefile linux-2.4.22/fs/reiserfs/Makefile
--- linux-2.4.22.orig/fs/reiserfs/Makefile	2003-10-02 18:37:44.000000000 +0400
+++ linux-2.4.22/fs/reiserfs/Makefile	2003-10-02 18:51:04.000000000 +0400
@@ -13,6 +13,8 @@
 
 obj-m   := $(O_TARGET)
 
+obj-$(CONFIG_REISERFS_BADBLOCKS) += badblocks.o
+
 # gcc -O2 (the kernel default)  is overaggressive on ppc32 when many inline
 # functions are used.  This causes the compiler to advance the stack
 # pointer out of the available stack space, corrupting kernel space,
diff -uNr linux-2.4.22.orig/fs/reiserfs/badblocks.c linux-2.4.22/fs/reiserfs/badblocks.c
--- linux-2.4.22.orig/fs/reiserfs/badblocks.c	1970-01-01 03:00:00.000000000 +0300
+++ linux-2.4.22/fs/reiserfs/badblocks.c	2003-10-02 19:07:02.000000000 +0400
@@ -0,0 +1,263 @@
+/*
+ * Copyright 2002, 2003 by Hans Reiser, licensing governed by reiserfs/README
+ */
+
+#include <linux/locks.h>
+#include <linux/smp_lock.h>
+#include <linux/reiserfs_fs.h>
+
+
+static int handle_badblocks_add(unsigned long blocknr, struct super_block *super)
+{
+	struct reiserfs_transaction_handle th;
+	struct cpu_key badblocks_key;
+	struct item_head badblocks_ih;
+	int retval;
+	unsigned int block_ondisk; // Should it be 32 bit, as we only have 32bit
+				   // blocknumbers in on-disk format?
+	INITIALIZE_PATH (path);
+	int windex;
+	int bitmap_block, offset;
+	
+	lock_kernel();
+	// check that block is not busy yet here.
+	bitmap_block = blocknr / ( super->s_blocksize << 3 );
+	offset = blocknr % ( super->s_blocksize << 3 );
+	if ( reiserfs_test_le_bit( offset,
+			SB_AP_BITMAP( super )[ bitmap_block ].bh -> b_data )) {
+		/* Block is already busy, so it cannot be marked as bad
+		   while filesystem is online */
+		unlock_kernel();
+		return -EBUSY;
+	}
+
+	/* Construct a key of object to which we bind bad blocks */
+	badblocks_key.version = KEY_FORMAT_3_5;
+	badblocks_key.on_disk_key.k_dir_id = 1;
+	badblocks_key.on_disk_key.k_objectid = MAX_KEY_OBJECTID;
+	set_cpu_key_k_offset (&badblocks_key, -1); //MAX_KEY_OFFSET);
+	set_cpu_key_k_type (&badblocks_key, TYPE_INDIRECT);
+	badblocks_key.key_length = 3;
+
+	windex = push_journal_writer("handle_badblocks_add") ;
+	/* One extra block for bitmap corresponding to the bad block */
+	journal_begin(&th, super, JOURNAL_PER_BALANCE_CNT + 1) ;
+
+	// Mark block as used
+	reiserfs_prepare_for_journal( super,
+				     SB_AP_BITMAP( super )[ bitmap_block ].bh, 1 );
+	if ( reiserfs_test_and_set_le_bit( offset,
+			SB_AP_BITMAP( super )[ bitmap_block ].bh -> b_data ) ) {
+		/* Sigh, block became busy while we made our preparation,
+		   abandon our furtile attempts, then */
+		reiserfs_restore_prepared_buffer( super,
+					SB_AP_BITMAP( super )[ bitmap_block ].bh );
+		retval = -EBUSY;
+		goto finish;
+	}
+	// Update superblock free blocks statistics
+	reiserfs_prepare_for_journal( super, SB_BUFFER_WITH_SB( super ), 1 );
+	PUT_SB_FREE_BLOCKS( super, SB_FREE_BLOCKS(super) - 1 );
+	/* Note that we postpone marking journal dirty until all
+	   following operations will succeed */
+
+	block_ondisk = cpu_to_le32 ( blocknr );
+
+	/* Now let's see if there is such object already */
+	retval = search_for_position_by_key (super, &badblocks_key, &path);
+
+	if ( retval == FILE_NOT_FOUND) {
+		/* No such object, so we need to create it */
+		make_le_item_head (&badblocks_ih, &badblocks_key,
+		        badblocks_key.version, 1, TYPE_INDIRECT,
+			UNFM_P_SIZE, 0/*free space*/);
+		retval = reiserfs_insert_item (&th, &path, &badblocks_key,
+					       &badblocks_ih,
+					       (char *)&block_ondisk);
+	} else if ( retval == POSITION_NOT_FOUND ) {
+		struct item_head *ih = get_ih (&path);
+		
+		set_cpu_key_k_offset (&badblocks_key, path.pos_in_item * super->s_blocksize + le_ih_k_offset(ih));
+		retval = reiserfs_paste_into_item (&th, &path, &badblocks_key, (char *)&block_ondisk, UNFM_P_SIZE);
+	} else {
+		reiserfs_warning(super, "Existing object, but no indirect item"
+					" while adding bad block? Confused and"
+					" giving up\n");
+	}
+	pathrelse(&path);
+	if ( retval ) {
+		// Well, pasting failed for some reason, it means we
+		// must reject our changes to bitmap
+
+		reiserfs_restore_prepared_buffer( super,
+					SB_AP_BITMAP( super )[ bitmap_block ].bh );
+		reiserfs_restore_prepared_buffer( super,
+					SB_BUFFER_WITH_SB( super ) );
+	} else {
+		journal_mark_dirty( &th, super, SB_AP_BITMAP( super )[ bitmap_block ].bh );
+		journal_mark_dirty( &th, super, SB_BUFFER_WITH_SB( super ) );
+	}
+	
+finish:
+	journal_end(&th, super, JOURNAL_PER_BALANCE_CNT + 1) ;
+	pop_journal_writer(windex);
+	unlock_kernel();
+	reiserfs_check_path(&path) ;
+	return retval;
+}
+
+static int handle_badblocks_remove(unsigned long blocknr, struct super_block *super)
+{
+	struct reiserfs_transaction_handle th;
+	struct cpu_key badblocks_key;
+	int retval;
+	unsigned int block_ondisk; // Should it be 32 bit, as we only have 32bit
+				   // blocknumbers in on-disk format?
+	INITIALIZE_PATH (path);
+	int windex;
+	int bitmap_block, offset;
+	
+	lock_kernel();
+	// check that block is not free yet here.
+	bitmap_block = blocknr / ( super->s_blocksize << 3 );
+	offset = blocknr % ( super->s_blocksize << 3 );
+	if ( !reiserfs_test_le_bit( offset,
+			SB_AP_BITMAP( super )[ bitmap_block ].bh -> b_data )) {
+		/* Block is already free */
+		unlock_kernel();
+		return -EBUSY;
+	}
+
+	/* Construct a key of object to which we bind bad blocks */
+	badblocks_key.version = KEY_FORMAT_3_5;
+	badblocks_key.on_disk_key.k_dir_id = 1;
+	badblocks_key.on_disk_key.k_objectid = MAX_KEY_OBJECTID;
+	set_cpu_key_k_offset (&badblocks_key, 1);
+	set_cpu_key_k_type (&badblocks_key, TYPE_INDIRECT);
+	badblocks_key.key_length = 3;
+
+	windex = push_journal_writer("handle_badblocks_remove") ;
+	/* One extra block for bitmap corresponding to the bad block */
+	journal_begin(&th, super, JOURNAL_PER_BALANCE_CNT + 1) ;
+
+
+	block_ondisk = cpu_to_le32 ( blocknr );
+
+	/* Now let's see if there is such object already */
+	retval = search_for_position_by_key (super, &badblocks_key, &path);
+
+// Probably only while loop alone can be left as result won't change.
+	if ( retval == FILE_NOT_FOUND) {
+		/* No such object, so there is no accounted bad blocks at all */
+		retval = -ENODATA;
+		goto finish;
+	} else if ( retval == POSITION_FOUND ) {
+		int cut_offset = 1, fs_gen, i;
+		struct item_head *ih;
+		__u32 * item;
+research:
+		while ( retval == POSITION_FOUND ) {
+
+			ih = get_ih (&path);
+			item = get_item (&path);
+			for ( i=0; i < I_UNFM_NUM (ih) ; i++) {
+				if ( get_block_num(item, i) == blocknr)
+					break;
+			}
+			cut_offset += i * super->s_blocksize;
+			set_cpu_key_k_offset ( &badblocks_key, cut_offset);
+			if ( i != I_UNFM_NUM (ih))
+				break; // found block number in the list.
+			retval = search_for_position_by_key (super, &badblocks_key, &path);
+		}
+		if ( retval != POSITION_FOUND ) {
+			/* Block was not found in the list, so abandon
+			   the operation */
+			retval = -ENODATA;
+			goto finish;
+		}
+		fs_gen = get_generation ( super );
+		reiserfs_prepare_for_journal(super, get_last_bh(&path), 1);
+		if ( fs_changed (fs_gen, super) && item_moved (ih, &path)) {
+			reiserfs_restore_prepared_buffer(super, get_last_bh(&path));
+			retval = search_for_position_by_key (super, &badblocks_key, &path);
+			goto research;
+		}
+			
+		/* Now we have correct offset, since block may be
+		   in the middle of indirect item and there is no code
+		   to cut stuff from the middle of a file, we simply put
+		   a zero instead of old block number.
+		   Right now we rely on fsck to clean up the stuff. */
+		put_block_num(item, path.pos_in_item+i, 0);
+		journal_mark_dirty (&th, super, get_last_bh(&path));
+		retval = 0;
+	} else {
+		reiserfs_warning(super, "Something strange is going on"
+					" while removing bad block? Confused and"
+					" giving up\n");
+	}
+	// Mark block as free
+	if ( !retval ) {
+	reiserfs_prepare_for_journal( super,
+				     SB_AP_BITMAP( super )[ bitmap_block ].bh, 1 );
+		if ( !reiserfs_test_and_clear_le_bit( offset,
+			SB_AP_BITMAP( super )[ bitmap_block ].bh -> b_data ) ) {
+		/* Sigh, block became free while we made our preparation,
+		   abandon our futile attempts, then */
+			reiserfs_restore_prepared_buffer( super,
+					SB_AP_BITMAP( super )[ bitmap_block ].bh );
+			retval = -EBUSY;
+			goto finish;
+		}
+		// Update superblock free blocks statistics
+		reiserfs_prepare_for_journal( super, SB_BUFFER_WITH_SB( super ), 1 );
+		PUT_SB_FREE_BLOCKS( super, SB_FREE_BLOCKS(super) + 1 );
+		journal_mark_dirty( &th, super, SB_AP_BITMAP( super )[ bitmap_block ].bh );
+		journal_mark_dirty( &th, super, SB_BUFFER_WITH_SB( super ) );
+	}
+	
+finish:
+	pathrelse(&path);
+	journal_end(&th, super, JOURNAL_PER_BALANCE_CNT + 1) ;
+	pop_journal_writer(windex);
+	unlock_kernel();
+	reiserfs_check_path(&path) ;
+	return retval;
+}
+
+
+int reiserfs_handle_badblocks_ioctl (int cmd, unsigned long blocknr, struct super_block *super)
+{
+
+	if (cmd == REISERFS_IOC_BADCNT) {
+		printk("Not yet implemented\n");
+		return -ENOTTY;
+	}
+	
+	if ( blocknr >= le32_to_cpu( super -> u.reiserfs_sb.s_rs ->  s_v1.s_block_count )) {
+		return -EINVAL; // attempt to mark a block beyond FS.
+	}
+	if ( ( blocknr >= SB_ONDISK_JOURNAL_1st_BLOCK( super ) )
+	    && ( blocknr < ( SB_ONDISK_JOURNAL_1st_BLOCK( super ) +
+	    JOURNAL_BLOCK_COUNT ) ) ) {
+		return -EINVAL; // attempt to mark bad block inside of journal area.
+	}
+
+#ifdef CONFIG_REISERFS_CHECK
+	if ( !is_reusable( super, blocknr, 2 ) ) { 
+		// we do want only consistency checks, so we pass illegal single
+		// bit value of 2.
+		return -EINVAL;
+	}
+#endif
+	if ( cmd == REISERFS_IOC_MARKBAD )
+		return handle_badblocks_add( blocknr, super);
+
+	if ( cmd == REISERFS_IOC_UNMARKBAD )
+		return handle_badblocks_remove( blocknr, super);
+
+	reiserfs_warning(super, "Invalid ioctl value for badblocks handler\n");
+
+	return -ENOTTY;
+}
diff -uNr linux-2.4.22.orig/fs/reiserfs/ioctl.c linux-2.4.22/fs/reiserfs/ioctl.c
--- linux-2.4.22.orig/fs/reiserfs/ioctl.c	2003-10-02 18:37:44.000000000 +0400
+++ linux-2.4.22/fs/reiserfs/ioctl.c	2003-10-02 18:51:04.000000000 +0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2002 by Hans Reiser, licensing governed by reiserfs/README
+ * Copyright 2000-2003 by Hans Reiser, licensing governed by reiserfs/README
  */
 
 #include <linux/fs.h>
@@ -81,6 +81,15 @@
 		inode->i_ctime = CURRENT_TIME;
 		mark_inode_dirty(inode);
 		return 0;
+#if defined( CONFIG_REISERFS_BADBLOCKS )
+	case REISERFS_IOC_MARKBAD:
+	case REISERFS_IOC_UNMARKBAD:
+	case REISERFS_IOC_BADCNT:
+		if( !capable( CAP_SYS_ADMIN ) )
+			return -EPERM;
+		else
+			return reiserfs_handle_badblocks_ioctl( cmd, arg, inode->i_sb );
+#endif
 	default:
 		return -ENOTTY;
 	}
diff -uNr linux-2.4.22.orig/fs/reiserfs/stree.c linux-2.4.22/fs/reiserfs/stree.c
--- linux-2.4.22.orig/fs/reiserfs/stree.c	2003-10-02 18:37:44.000000000 +0400
+++ linux-2.4.22/fs/reiserfs/stree.c	2003-10-02 18:51:04.000000000 +0400
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2000-2002 by Hans Reiser, licensing governed by reiserfs/README
+ *  Copyright 2000-2003 by Hans Reiser, licensing governed by reiserfs/README
  */
 
 /*
@@ -849,6 +849,7 @@
     n_blk_size = p_s_sb->s_blocksize;
 
     if (comp_short_keys (&(p_le_ih->ih_key), p_cpu_key)) {
+        PATH_LAST_POSITION(p_s_search_path)++;
 	return FILE_NOT_FOUND;
     }
 
diff -uNr linux-2.4.22.orig/include/linux/reiserfs_fs.h linux-2.4.22/include/linux/reiserfs_fs.h
--- linux-2.4.22.orig/include/linux/reiserfs_fs.h	2003-10-02 18:37:53.000000000 +0400
+++ linux-2.4.22/include/linux/reiserfs_fs.h	2003-10-02 19:08:16.000000000 +0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 1996-2002 Hans Reiser, see reiserfs/README for licensing and copyright details
+ * Copyright 1996-2003 Hans Reiser, see reiserfs/README for licensing and copyright details
  */
 
 				/* this file has an amazingly stupid
@@ -2067,6 +2067,9 @@
 void make_empty_node (struct buffer_info *);
 struct buffer_head * get_FEB (struct tree_balance *);
 
+/* badblocks.c */
+int reiserfs_handle_badblocks_ioctl (int cmd, unsigned long blocknr, struct super_block *super);
+
 /* bitmap.c */
 
 /* structure contains hints for block allocator, and it is a container for
@@ -2188,6 +2191,10 @@
 #define REISERFS_IOC_SETFLAGS           EXT2_IOC_SETFLAGS
 #define REISERFS_IOC_GETVERSION 	EXT2_IOC_GETVERSION
 #define REISERFS_IOC_SETVERSION         EXT2_IOC_SETVERSION
+#define REISERFS_IOC_MARKBAD		_IOW(0xCD,2,long)
+#define REISERFS_IOC_UNMARKBAD		_IOW(0xCD,3,long)
+#define REISERFS_IOC_BADCNT		_IOW(0xCD,4,long)
+
  			         
 #endif /* _LINUX_REISER_FS_H */
 
