    H-bad-blocks.patch
    Add crude form of online bad-block handling to the reiserfs.
    New ioctl is provided to mark bad-blocks "used" in block allocation
    bitmap. User-level utility is available at 
    namesys.com/bad-block-handling.html
diff -rup linux-2.4.6/fs/reiserfs/bitmap.c linux-2.4.6.cleanup/fs/reiserfs/bitmap.c
--- linux-2.4.6/fs/reiserfs/bitmap.c	Sun Jul 15 16:21:24 2001
+++ linux-2.4.6.cleanup/fs/reiserfs/bitmap.c	Sun Jul 15 16:22:19 2001
@@ -688,3 +688,103 @@ 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 >= reiserfs_get_journal_block( super ) ) &&
+	    ( blocknr < ( reiserfs_get_journal_block( super ) + 
+			  JOURNAL_BLOCK_COUNT ) ) ) {
+		REISERFS_LOG( "bb", 
+			      "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( "bb", 
+			      "Attempt to mark one of first 0x%lx blocks in use",
+			      ( unsigned long ) first_block );
+	}
+#if defined( CONFIG_REISERFS_CHECK )
+	else if( !is_reusable( super, blocknr, used ? 0 : 1 ) ) {
+		REISERFS_LOG( "bb", "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( "bb",  */
+		/*   "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( "bb", "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 ( "bb", 
+					       "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.6/fs/reiserfs/dir.c linux-2.4.6.cleanup/fs/reiserfs/dir.c
--- linux-2.4.6/fs/reiserfs/dir.c	Sun Jul 15 16:21:19 2001
+++ linux-2.4.6.cleanup/fs/reiserfs/dir.c	Sun Jul 15 16:22:19 2001
@@ -217,23 +217,3 @@ static int reiserfs_readdir (struct file
     return 0;
 }
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Only in linux-2.4.6.cleanup/fs/reiserfs: do_balan.c~
diff -rup linux-2.4.6/fs/reiserfs/ioctl.c linux-2.4.6.cleanup/fs/reiserfs/ioctl.c
--- linux-2.4.6/fs/reiserfs/ioctl.c	Sun Jul 15 16:12:03 2001
+++ linux-2.4.6.cleanup/fs/reiserfs/ioctl.c	Sun Jul 15 16:22:19 2001
@@ -14,7 +14,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)
@@ -23,7 +25,42 @@ 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.6/include/linux/reiserfs_fs.h linux-2.4.6.cleanup/include/linux/reiserfs_fs.h
--- linux-2.4.6/include/linux/reiserfs_fs.h	Sun Jul 15 16:21:35 2001
+++ linux-2.4.6.cleanup/include/linux/reiserfs_fs.h	Sun Jul 15 16:22:19 2001
@@ -67,6 +67,11 @@
 /* enable journalling */
 #define ENABLE_JOURNAL
 
+/* handle bad blocks by marking them used in the bitmap */
+#define REISERFS_HANDLE_BADBLOCKS
+
+#define USE_INODE_GENERATION_COUNTER
+
 #ifdef __KERNEL__
 
 /* #define REISERFS_CHECK */
@@ -121,6 +126,13 @@ if( !( cond ) ) 								\
 /*                             SUPER BLOCK                                 */
 /***************************************************************************/
 
+/* 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 )
+
 /*
  * Structure of super block on disk, a version of which in RAM is often accessed as s->u.reiserfs_sb.s_rs
  * the version in RAM is part of a larger structure containing fields never written to disk.
@@ -1571,6 +1583,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(const struct buffer_head *bh) {
   if (bh && test_bit(BH_JPrepared, ( struct buffer_head * ) &bh->b_state))
@@ -2066,6 +2091,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 */
 
Only in linux-2.4.6.cleanup/include/linux: reiserfs_fs.h.orig
Only in linux-2.4.6.cleanup/include/linux: reiserfs_fs.h.rej
diff -rup linux-2.4.6/include/linux/reiserfs_fs_sb.h linux-2.4.6.cleanup/include/linux/reiserfs_fs_sb.h
--- linux-2.4.6/include/linux/reiserfs_fs_sb.h	Sun Jul 15 16:21:24 2001
+++ linux-2.4.6.cleanup/include/linux/reiserfs_fs_sb.h	Sun Jul 15 16:22:19 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 
@@ -40,54 +40,59 @@ struct reiserfs_super_block
 
 				/* great comment Chris. Thanks.  -Hans */
 
-  __u32 s_orig_journal_size; 		
-  __u32 s_journal_trans_max ;           /* max number of blocks in a transaction.  */
-  __u32 s_journal_block_count ;         /* total size of the journal. can change over time  */
-  __u32 s_journal_max_batch ;           /* max number of blocks to batch into a trans */
-  __u32 s_journal_max_commit_age ;      /* in seconds, how old can an async commit be */
-  __u32 s_journal_max_trans_age ;       /* in seconds, how old can a transaction be */
-  __u16 s_blocksize;                   	/* block size           */
-  __u16 s_oid_maxsize;			/* max size of object id array, see get_objectid() commentary  */
-  __u16 s_oid_cursize;			/* current size of object id array */
-  __u16 s_state;                       	/* valid or error       */
-  char s_magic[12];                     /* reiserfs magic string indicates that file system is reiserfs */
-  __u32 s_hash_function_code;		/* indicate, what hash function is being use to sort names in a directory*/
-  __u16 s_tree_height;                  /* height of disk tree */
-  __u16 s_bmap_nr;                      /* amount of bitmap blocks needed to address each block of file system */
-  __u16 s_version;		/* I'd prefer it if this was a string,
+  /* 20 */  __u32 s_orig_journal_size; 		
+  /* 24 */  __u32 s_journal_trans_max ;           /* max number of blocks in a transaction.  */
+  /* 28 */  __u32 s_journal_block_count ;         /* total size of the journal. can change over time  */
+  /* 32 */  __u32 s_journal_max_batch ;           /* max number of blocks to batch into a trans */
+  /* 36 */  __u32 s_journal_max_commit_age ;      /* in seconds, how old can an async commit be */
+  /* 40 */  __u32 s_journal_max_trans_age ;       /* in seconds, how old can a transaction be */
+  /* 44 */  __u16 s_blocksize;                   	/* block size           */
+  /* 46 */  __u16 s_oid_maxsize;			/* max size of object id array, see get_objectid() commentary  */
+  /* 48 */  __u16 s_oid_cursize;			/* current size of object id array */
+  /* 50 */  __u16 s_state;                       	/* valid or error       */
+  /* 52 */  char s_magic[12];                     /* reiserfs magic string indicates that file system is reiserfs */
+  /* 64 */  __u32 s_hash_function_code;		/* indicate, what hash function is being use to sort names in a directory*/
+  /* 68 */  __u16 s_tree_height;                  /* height of disk tree */
+  /* 70 */  __u16 s_bmap_nr;                      /* amount of bitmap blocks needed to address each block of file system */
+  /* 72 */  __u16 s_version;		/* I'd prefer it if this was a string,
                                    something like "3.6.4", and maybe
                                    16 bytes long mostly unused. We
                                    don't need to save bytes in the
                                    superblock. -Hans */
-  __u16 s_reserved;
-  char s_unused[128] ;			/* zero filled by mkreiserfs */
-} __attribute__ ((__packed__));
+  /* 74 */  __u16 s_marked_in_use;
+  /* 76 */  __u16 s_inode_generation;
+  /* 76 */  char s_unused[124] ;			/* zero filled by mkreiserfs */
+  /* 202 */ char padding_to_quad[ 2 ];
+  /* 204 --- aligned to __u32 */
+};
 
 #define SB_SIZE (sizeof(struct reiserfs_super_block))
 
 /* this is the super from 3.5.X, where X >= 10 */
 struct reiserfs_super_block_v1
 {
-  __u32 s_block_count;			/* blocks 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  */
-  __u32 s_orig_journal_size; 		/* size of the journal on FS creation.  used to make sure they don't overflow it */
-  __u32 s_journal_trans_max ;           /* max number of blocks in a transaction.  */
-  __u32 s_journal_block_count ;         /* total size of the journal. can change over time  */
-  __u32 s_journal_max_batch ;           /* max number of blocks to batch into a trans */
-  __u32 s_journal_max_commit_age ;      /* in seconds, how old can an async commit be */
-  __u32 s_journal_max_trans_age ;       /* in seconds, how old can a transaction be */
-  __u16 s_blocksize;                   	/* block size           */
-  __u16 s_oid_maxsize;			/* max size of object id array, see get_objectid() commentary  */
-  __u16 s_oid_cursize;			/* current size of object id array */
-  __u16 s_state;                       	/* valid or error       */
-  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;
-} __attribute__ ((__packed__));
+  /*  0 */  __u32 s_block_count;			/* blocks 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  */
+  /* 20 */  __u32 s_orig_journal_size; 		/* size of the journal on FS creation.  used to make sure they don't overflow it */
+  /* 24 */  __u32 s_journal_trans_max ;           /* max number of blocks in a transaction.  */
+  /* 28 */  __u32 s_journal_block_count ;         /* total size of the journal. can change over time  */
+  /* 32 */  __u32 s_journal_max_batch ;           /* max number of blocks to batch into a trans */
+  /* 36 */  __u32 s_journal_max_commit_age ;      /* in seconds, how old can an async commit be */
+  /* 40 */  __u32 s_journal_max_trans_age ;       /* in seconds, how old can a transaction be */
+  /* 44 */  __u16 s_blocksize;                   	/* block size           */
+  /* 46 */  __u16 s_oid_maxsize;			/* max size of object id array, see get_objectid() commentary  */
+  /* 48 */  __u16 s_oid_cursize;			/* current size of object id array */
+  /* 50 */  __u16 s_state;                       	/* valid or error       */
+  /* 52 */  char s_magic[16];                     /* reiserfs magic string indicates that file system is reiserfs */
+  /* 68 */  __u16 s_tree_height;                  /* height of disk tree */
+  /* 70 */  __u16 s_bmap_nr;                      /* amount of bitmap blocks needed to address each block of file system */
+  /* 72 */  __u16 s_reserved;
+  /* 74 */  __u16 s_marked_in_use;
+  /* 76 --- aligned to __u32 */
+};
 
 #define SB_SIZE_V1 (sizeof(struct reiserfs_super_block_v1))
 
