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))