diff -rup linux-2.4.8/fs/reiserfs/bitmap.c linux-2.4.8-bb/fs/reiserfs/bitmap.c
--- linux-2.4.8/fs/reiserfs/bitmap.c	Wed May  2 14:04:15 2001
+++ linux-2.4.8-bb/fs/reiserfs/bitmap.c	Wed Aug 22 13:55:24 2001
@@ -716,3 +716,118 @@ void reiserfs_discard_all_prealloc (stru
   }
 }
 #endif
+
+
+#if defined( REISERFS_HANDLE_BADBLOCKS )
+int mark_in_use_on_user_behalf( struct reiserfs_transaction_handle *th,
+				unsigned long blocknr, int used )
+{
+#if !defined( SUPPORT_OLD_FORMAT )
+#define first_block ( REISERFS_DISK_OFFSET_IN_BYTES / block_size )
+#else
+#define first_block ( REISERFS_OLD_DISK_OFFSET_IN_BYTES / block_size )
+#endif
+
+  struct super_block *super;
+  int block_size;
+  int result;
+
+  super = th -> t_super;
+#if !defined( SUPPORT_OLD_FORMAT )
+  block_size = super -> s_blocksize;
+#else
+  block_size = REISERFS_OLD_BLOCKSIZE;
+#endif
+
+  result = -EINVAL;
+  if( blocknr >= le32_to_cpu( super -> u.reiserfs_sb.s_rs -> s_block_count ) )
+    {
+      REISERFS_LOG( "mark-used-too-far", 
+		    "Attempt to mark block beyond file-system: "
+		    "0x%lx >= 0x%lx", 
+		    blocknr,
+		    le32_to_cpu( super -> u.reiserfs_sb.s_rs -> s_block_count )
+	      );
+    }
+  else if( ( blocknr >= reiserfs_get_journal_block( super ) ) &&
+      ( blocknr < ( reiserfs_get_journal_block( super ) + 
+		    JOURNAL_BLOCK_COUNT ) ) )
+    {
+      REISERFS_LOG( "mark-journal-used", 
+		    "Attempt to mark journal block in use is futile: "
+		    "0x%lx in [0x%lx, 0x%lx)", 
+		    blocknr, 
+		    reiserfs_get_journal_block( super ), 
+		    reiserfs_get_journal_block( super ) + JOURNAL_BLOCK_COUNT );
+    }
+  else if( blocknr <= first_block )
+    {
+      REISERFS_LOG( "mark-boot-used", 
+		    "Attempt to mark one of first 0x%lx blocks in use is futile",
+		    ( unsigned long ) first_block );
+    }
+#if defined( CONFIG_REISERFS_CHECK )
+  else if( !is_reusable( super, blocknr, used ? 0 : 1 ) )
+    {
+      REISERFS_LOG( "mark-reusable-used", "is_reusable() barfs on block 0x%lx", blocknr );
+    }
+#endif
+  else
+    {
+      int bitmap_block;
+      int offset;
+
+      bitmap_block = blocknr / ( block_size << 3 );
+      offset = blocknr % ( block_size << 3 );
+
+      /* REISERFS_LOG( "trace",  */
+      /* 	    "bitmap_block: %x, offset: %x", bitmap_block, offset ); */
+
+      reiserfs_prepare_for_journal( super, 
+				    SB_AP_BITMAP( super )[ bitmap_block ], 1 );
+      if( ( used && 
+	    reiserfs_test_and_set_le_bit
+	    ( offset, 
+	      SB_AP_BITMAP( super )[ bitmap_block ] -> b_data ) != 0 ) ||
+	  ( !used && reiserfs_test_and_clear_le_bit
+	    ( offset, 
+	      SB_AP_BITMAP( super )[ bitmap_block ] -> b_data ) == 0 ) )
+	{
+	  REISERFS_LOG( "already-marked", "block 0x%lx already %s", blocknr,
+			used ? "in use" : "free" );
+	  reiserfs_restore_prepared_buffer
+	    ( super, 
+	      SB_AP_BITMAP( super )[ bitmap_block ] );
+	  result = -EBUSY;
+	}
+      else
+	{
+	  used = ( used ? -1 : +1 );
+	  journal_mark_dirty( th, super, 
+			      SB_AP_BITMAP( super )[ bitmap_block ] ); 
+	  reiserfs_prepare_for_journal( super, SB_BUFFER_WITH_SB( super ), 1 );
+	  super -> u.reiserfs_sb.s_rs -> s_free_blocks = 
+	    cpu_to_le32( SB_FREE_BLOCKS( super ) + used );
+	  if( le32_to_cpu( super -> 
+			   u.reiserfs_sb.s_rs -> s_marked_in_use ) < 0xffff )
+	    {
+	      super -> u.reiserfs_sb.s_rs -> s_marked_in_use = 
+		cpu_to_le32
+		( le32_to_cpu
+		  ( super -> u.reiserfs_sb.s_rs -> s_marked_in_use ) - 
+		  used );
+	    }
+	  else
+	    {
+	      REISERFS_LOG( "too-many-marked", "already have 0xffff of `bad' blocks" );
+	    }
+	  journal_mark_dirty( th, super, SB_BUFFER_WITH_SB( super ) );
+	  super -> s_dirt = 1;
+	  result = 0;
+	}
+    }
+  return result;
+}
+/* REISERFS_HANDLE_BADBLOCKS */
+#endif
+
diff -rup linux-2.4.8/fs/reiserfs/ioctl.c linux-2.4.8-bb/fs/reiserfs/ioctl.c
--- linux-2.4.8/fs/reiserfs/ioctl.c	Wed May  2 14:03:23 2001
+++ linux-2.4.8-bb/fs/reiserfs/ioctl.c	Wed Aug 22 13:55:24 2001
@@ -22,7 +22,9 @@
 ** supported commands:
 **  1) REISERFS_IOC_UNPACK - try to unpack tail from direct item into indirect
 **                           and prevent packing file (argument arg has to be non-zero)
-**  2) That's all for a while ...
+**  2) REISERFS_IOC_USED - arg is block number to be marked used in the bitmap.
+**     Used for bad-block handling.
+**  3) That's all for a while ...
 */
 int reiserfs_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
 		unsigned long arg)
@@ -31,7 +33,49 @@ int reiserfs_ioctl (struct inode * inode
 	    case REISERFS_IOC_UNPACK:
 		if (arg)
 		    return reiserfs_unpack (inode, filp);
+		break;	
+#if defined( REISERFS_HANDLE_BADBLOCKS )
+	    case REISERFS_IOC_USED:
+	    case REISERFS_IOC_FREE:
+	    case REISERFS_IOC_BADCNT:
+		  {
+			if( !capable( CAP_SYS_ADMIN ) )
+			  {
+				return -EPERM;
+			  }
+			else
+			  {
+				struct reiserfs_transaction_handle th;
+				int result;
+				int token;
 			
+				/* we can put into transaction two blocks: bitmap
+				   block and super-block. */
+				journal_begin( &th, inode -> i_sb, 2 );
+				token = push_journal_writer( "REISERFS_IOC_USED" );
+				if( cmd == REISERFS_IOC_BADCNT )
+				  {
+					reiserfs_prepare_for_journal
+					  ( inode -> i_sb, SB_BUFFER_WITH_SB( inode -> i_sb ), 1 );
+					inode -> i_sb -> u.reiserfs_sb.s_rs -> s_marked_in_use = 
+					  cpu_to_le32( ( __u32 ) arg );
+					journal_mark_dirty( &th, inode -> i_sb, 
+										SB_BUFFER_WITH_SB( inode -> i_sb ) );
+					inode -> i_sb -> s_dirt = 1;
+					result = 0;
+				  }
+				else
+				  {
+					result = mark_in_use_on_user_behalf
+					  ( &th, arg, ( cmd == REISERFS_IOC_USED ) ? 1 : 0  );
+				  }
+				pop_journal_writer( token ) ;
+				journal_end( &th, inode -> i_sb, 2 );
+				return result;
+			  }
+		  }
+/* REISERFS_HANDLE_BADBLOCKS */
+#endif
 	    default:
 		return -ENOTTY;
 	}
diff -rup linux-2.4.8/include/linux/reiserfs_fs.h linux-2.4.8-bb/include/linux/reiserfs_fs.h
--- linux-2.4.8/include/linux/reiserfs_fs.h	Mon Aug 13 15:31:43 2001
+++ linux-2.4.8-bb/include/linux/reiserfs_fs.h	Wed Aug 22 13:55:24 2001
@@ -68,6 +68,9 @@
 #define USE_INODE_GENERATION_COUNTER
 
 
+/* handle bad blocks by marking them used in the bitmap */
+#define REISERFS_HANDLE_BADBLOCKS
+
 #ifdef __KERNEL__
 
 /* #define REISERFS_CHECK */
@@ -98,6 +101,13 @@
 */
 #define REISERFS_DEBUG_CODE 5 /* extra messages to help find/debug errors */ 
 
+/* macro for debugging output */
+#define REISERFS_LOG( maintainer, format, args... )					\
+  do {																\
+  printk( "reiserfs: %s-%i %s:%s: " format "\n",					\
+		  ( maintainer ), __LINE__, __func__, __FILE__ ,  ##args );	\
+	} while( 0 )
+
 /*
  * Disk Data Structures
  */
@@ -1618,6 +1628,19 @@ int reiserfs_remove_page_from_flush_list
 
 int reiserfs_allocate_list_bitmaps(struct super_block *s, struct reiserfs_list_bitmap *, int) ;
 
+#if defined( REISERFS_HANDLE_BADBLOCKS )
+/** mark `blocknr' as being in use in bitmap, associated with
+	super-block in `th'. This is supposed to be called from special
+	ioctl() to handle bad blocks. Checks that `blocknr' is not in
+	journal area or before superblock. 
+
+	If `used' is not 0, mark it used, otherwise, mark it free.
+
+	Returns 0 on sucess and (-errno) on error. */
+int mark_in_use_on_user_behalf( struct reiserfs_transaction_handle *th,
+								unsigned long blocknr, int used );
+#endif
+
 				/* why is this kerplunked right here? */
 static inline int reiserfs_buffer_prepared(struct buffer_head *bh) {
   if (bh && test_bit(BH_JPrepared, &bh->b_state))
@@ -2053,6 +2076,11 @@ int reiserfs_unpack (struct inode * inod
  
 /* ioctl's command */
 #define REISERFS_IOC_UNPACK		_IOW(0xCD,1,long)
+#if defined( REISERFS_HANDLE_BADBLOCKS )
+#define REISERFS_IOC_USED		_IOW(0xCD,2,long)
+#define REISERFS_IOC_FREE		_IOW(0xCD,3,long)
+#define REISERFS_IOC_BADCNT 	_IOW(0xCD,4,long)
+#endif
  			         
 #endif /* _LINUX_REISER_FS_H */
 
diff -rup linux-2.4.8/include/linux/reiserfs_fs_sb.h linux-2.4.8-bb/include/linux/reiserfs_fs_sb.h
--- linux-2.4.8/include/linux/reiserfs_fs_sb.h	Wed Aug  1 17:21:13 2001
+++ linux-2.4.8-bb/include/linux/reiserfs_fs_sb.h	Wed Aug 22 14:00:53 2001
@@ -25,11 +25,11 @@
 
 struct reiserfs_super_block
 {
-  __u32 s_block_count;
-  __u32 s_free_blocks;                  /* free blocks count    */
-  __u32 s_root_block;           	/* root block number    */
-  __u32 s_journal_block;           	/* journal block number    */
-  __u32 s_journal_dev;           	/* journal device number  */
+  /* 0  */  __u32 s_block_count;
+  /* 4  */  __u32 s_free_blocks;                  /* free blocks count    */
+  /* 8  */  __u32 s_root_block;           	/* root block number    */
+  /* 12 */  __u32 s_journal_block;           	/* journal block number    */
+  /* 16 */  __u32 s_journal_dev;           	/* journal device number  */
 
   /* Since journal size is currently a #define in a header file, if 
   ** someone creates a disk with a 16MB journal and moves it to a 
@@ -59,7 +59,7 @@ struct reiserfs_super_block
                                    16 bytes long mostly unused. We
                                    don't need to save bytes in the
                                    superblock. -Hans */
-  __u16 s_reserved;
+  __u16 s_marked_in_use;
   __u32 s_inode_generation;
   char s_unused[124] ;			/* zero filled by mkreiserfs */
 } __attribute__ ((__packed__));
@@ -87,7 +87,8 @@ struct reiserfs_super_block_v1
   char s_magic[16];                     /* reiserfs magic string indicates that file system is reiserfs */
   __u16 s_tree_height;                  /* height of disk tree */
   __u16 s_bmap_nr;                      /* amount of bitmap blocks needed to address each block of file system */
-  __u32 s_reserved;
+  __u16 s_reserved;
+  __u16 s_marked_in_use;
 } __attribute__ ((__packed__));
 
 #define SB_SIZE_V1 (sizeof(struct reiserfs_super_block_v1))
Only in linux-2.4.8-bb: linux
