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__
+/* 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
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 @@
/* 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 */
+};
/* 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 */
+};