diff -rup linux-2.4.2/fs/reiserfs/bitmap.c linux-2.4.2-bb/fs/reiserfs/bitmap.c --- linux-2.4.2/fs/reiserfs/bitmap.c Tue Jan 16 02:31:19 2001 +++ linux-2.4.2-bb/fs/reiserfs/bitmap.c Wed Aug 22 13:34:47 2001 @@ -677,3 +677,118 @@ void reiserfs_discard_prealloc (struct r inode->u.reiserfs_i.i_prealloc_count = 0; } #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.2/fs/reiserfs/ioctl.c linux-2.4.2-bb/fs/reiserfs/ioctl.c --- linux-2.4.2/fs/reiserfs/ioctl.c Mon Jan 15 23:42:32 2001 +++ linux-2.4.2-bb/fs/reiserfs/ioctl.c Wed Aug 22 13:34:47 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.2/include/linux/reiserfs_fs.h linux-2.4.2-bb/include/linux/reiserfs_fs.h --- linux-2.4.2/include/linux/reiserfs_fs.h Thu Feb 22 20:04:00 2001 +++ linux-2.4.2-bb/include/linux/reiserfs_fs.h Wed Aug 22 13:34:47 2001 @@ -65,6 +65,9 @@ /* enable journalling */ #define ENABLE_JOURNAL +/* handle bad blocks by marking them used in the bitmap */ +#define REISERFS_HANDLE_BADBLOCKS + #ifdef __KERNEL__ /* #define REISERFS_CHECK */ @@ -95,6 +98,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 */ @@ -1637,6 +1647,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)) @@ -2068,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 */ diff -rup linux-2.4.2/include/linux/reiserfs_fs_sb.h linux-2.4.2-bb/include/linux/reiserfs_fs_sb.h --- linux-2.4.2/include/linux/reiserfs_fs_sb.h Tue Jan 30 10:24:56 2001 +++ linux-2.4.2-bb/include/linux/reiserfs_fs_sb.h Wed Aug 22 13:34:47 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; + /* 78 */ 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)) .