bb_inode.c revision 8f82ef9860339039b54a324be137fbc09b762358
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/* 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * bb_inode.c --- routines to update the bad block inode. 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * WARNING: This routine modifies a lot of state in the filesystem; if 5a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch * this routine returns an error, the bad block inode may be in an 65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * inconsistent state. 7b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) * 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Copyright (C) 1994, 1995 Theodore Ts'o. 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * %Begin-Header% 1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * This file may be redistributed under the terms of the GNU Public 12ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * License. 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * %End-Header% 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include <stdio.h> 177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include <string.h> 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if HAVE_UNISTD_H 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <unistd.h> 20a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#endif 21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include <fcntl.h> 22a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include <time.h> 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if HAVE_SYS_STAT_H 243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include <sys/stat.h> 253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#endif 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if HAVE_SYS_TYPES_H 27effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include <sys/types.h> 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ext2_fs.h" 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ext2fs.h" 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct set_badblock_record { 347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ext2_badblocks_iterate bb_iter; 357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) int bad_block_count; 367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) blk_t *ind_blocks; 37a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch int max_ind_blocks; 38ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch int ind_blocks_size; 393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) int ind_blocks_ptr; 407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) char *block_buf; 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) errcode_t err; 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)static int set_bad_block_proc(ext2_filsys fs, blk_t *block_nr, 457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) e2_blkcnt_t blockcnt, 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blk_t ref_block, int ref_offset, 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void *priv_data); 487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)static int clear_bad_block_proc(ext2_filsys fs, blk_t *block_nr, 497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) e2_blkcnt_t blockcnt, 50a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) blk_t ref_block, int ref_offset, 51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) void *priv_data); 52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)/* 54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * Given a bad blocks bitmap, update the bad blocks inode to reflect 55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * the map. 56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) */ 57a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)errcode_t ext2fs_update_bb_inode(ext2_filsys fs, ext2_badblocks_list bb_list) 58a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles){ 59a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) errcode_t retval; 607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) struct set_badblock_record rec; 617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) struct ext2_inode inode; 627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!fs->block_map) 66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return EXT2_ET_NO_BLOCK_BITMAP; 6768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 6868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) rec.bad_block_count = 0; 6968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) rec.ind_blocks_size = rec.ind_blocks_ptr = 0; 7068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) rec.max_ind_blocks = 10; 7168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) retval = ext2fs_get_array(rec.max_ind_blocks, sizeof(blk_t), 7268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) &rec.ind_blocks); 734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (retval) 744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return retval; 754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) memset(rec.ind_blocks, 0, rec.max_ind_blocks * sizeof(blk_t)); 764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) retval = ext2fs_get_mem(fs->blocksize, &rec.block_buf); 774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (retval) 784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) goto cleanup; 794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) memset(rec.block_buf, 0, fs->blocksize); 804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) rec.err = 0; 814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) /* 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * First clear the old bad blocks (while saving the indirect blocks) 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) */ 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO, 8668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) BLOCK_FLAG_DEPTH_TRAVERSE, 0, 8768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) clear_bad_block_proc, &rec); 887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (retval) 897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) goto cleanup; 907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (rec.err) { 917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch retval = rec.err; 927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch goto cleanup; 937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) /* 967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * Now set the bad blocks! 971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) * 987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * First, mark the bad blocks as used. This prevents a bad 997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * block from being used as an indirecto block for the bad 100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * block inode (!). 101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) */ 102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (bb_list) { 1037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) retval = ext2fs_badblocks_list_iterate_begin(bb_list, 1047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) &rec.bb_iter); 1058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (retval) 1068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) goto cleanup; 1078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO, 1088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) BLOCK_FLAG_APPEND, 0, 1097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) set_bad_block_proc, &rec); 1104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ext2fs_badblocks_list_iterate_end(rec.bb_iter); 111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (retval) 1124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) goto cleanup; 1134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (rec.err) { 1144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) retval = rec.err; 1158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) goto cleanup; 1168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 1178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 1188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 1198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) /* 1204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Update the bad block inode's mod time and block count 1217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * field. 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) retval = ext2fs_read_inode(fs, EXT2_BAD_INO, &inode); 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (retval) 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) goto cleanup; 1267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 1277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) inode.i_atime = inode.i_mtime = fs->now ? fs->now : time(0); 1287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!inode.i_ctime) 1297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) inode.i_ctime = fs->now ? fs->now : time(0); 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ext2fs_iblk_set(fs, &inode, rec.bad_block_count); 131424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) inode.i_size = rec.bad_block_count * fs->blocksize; 132ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 133ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch retval = ext2fs_write_inode(fs, EXT2_BAD_INO, &inode); 13458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (retval) 135424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) goto cleanup; 1367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 137424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)cleanup: 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ext2fs_free_mem(&rec.ind_blocks); 1397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ext2fs_free_mem(&rec.block_buf); 1404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return retval; 1414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)/* 1447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * Helper function for update_bb_inode() 1451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) * 1461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) * Clear the bad blocks in the bad block inode, while saving the 1471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) * indirect blocks. 1481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) */ 1497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#ifdef __TURBOC__ 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) #pragma argsused 1511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#endif 1521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)static int clear_bad_block_proc(ext2_filsys fs, blk_t *block_nr, 1531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) e2_blkcnt_t blockcnt, 1541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) blk_t ref_block EXT2FS_ATTR((unused)), 1554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) int ref_offset EXT2FS_ATTR((unused)), 1561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) void *priv_data) 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){ 1581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) struct set_badblock_record *rec = (struct set_badblock_record *) 1591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) priv_data; 1601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) errcode_t retval; 1611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) unsigned long old_size; 1627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!*block_nr) 1647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return 0; 165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) /* 1673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * If the block number is outrageous, clear it and ignore it. 1681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) */ 1693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (*block_nr >= fs->super->s_blocks_count || 1703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) *block_nr < fs->super->s_first_data_block) { 1713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) *block_nr = 0; 1723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return BLOCK_CHANGED; 173eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 1741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (blockcnt < 0) { 1761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (rec->ind_blocks_size >= rec->max_ind_blocks) { 1773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) old_size = rec->max_ind_blocks * sizeof(blk_t); 1783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) rec->max_ind_blocks += 10; 1791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) retval = ext2fs_resize_mem(old_size, 1801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) rec->max_ind_blocks * sizeof(blk_t), 181a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) &rec->ind_blocks); 182c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (retval) { 1831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) rec->max_ind_blocks -= 10; 1841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) rec->err = retval; 1851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return BLOCK_ABORT; 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 188a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) rec->ind_blocks[rec->ind_blocks_size++] = *block_nr; 189a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 1903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) /* 1927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * Mark the block as unused, and update accounting information 193a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) */ 194a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ext2fs_block_alloc_stats(fs, *block_nr, -1); 195a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 196a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) *block_nr = 0; 197ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return BLOCK_CHANGED; 198a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 199a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 200a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 201a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)/* 202ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * Helper function for update_bb_inode() 203ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * 204ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * Set the block list in the bad block inode, using the supplied bitmap. 205ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch */ 206ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#ifdef __TURBOC__ 207ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch #pragma argsused 208ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#endif 20958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)static int set_bad_block_proc(ext2_filsys fs, blk_t *block_nr, 21058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) e2_blkcnt_t blockcnt, 21158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) blk_t ref_block EXT2FS_ATTR((unused)), 21258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) int ref_offset EXT2FS_ATTR((unused)), 21358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) void *priv_data) 21458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles){ 21558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) struct set_badblock_record *rec = (struct set_badblock_record *) 21658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) priv_data; 2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) errcode_t retval; 2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blk_t blk; 219a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (blockcnt >= 0) { 221a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch /* 2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * Get the next bad block. 2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) */ 224a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!ext2fs_badblocks_list_iterate(rec->bb_iter, &blk)) 2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return BLOCK_ABORT; 2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) rec->bad_block_count++; 2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) /* 2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * An indirect block; fetch a block from the 230a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch * previously used indirect block list. The block 2313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * most be not marked as used; if so, get another one. 2323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * If we run out of reserved indirect blocks, allocate 233a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch * a new one. 234a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch */ 235424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) retry: 236424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (rec->ind_blocks_ptr < rec->ind_blocks_size) { 237a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch blk = rec->ind_blocks[rec->ind_blocks_ptr++]; 238a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch if (ext2fs_test_block_bitmap2(fs->block_map, blk)) 2393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) goto retry; 240424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } else { 241a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch retval = ext2fs_new_block(fs, 0, 0, &blk); 242a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch if (retval) { 243a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch rec->err = retval; 2448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return BLOCK_ABORT; 2458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 2468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 2478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) retval = io_channel_write_blk(fs->io, blk, 1, rec->block_buf); 2488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (retval) { 2498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) rec->err = retval; 250a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch return BLOCK_ABORT; 251424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 252a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch } 253a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) /* 255a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch * Update block counts 256a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch */ 2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ext2fs_block_alloc_stats(fs, blk, +1); 2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *block_nr = blk; 2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return BLOCK_CHANGED; 2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 264a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 265a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 266a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 267a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 268a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch