Magellan Linux

Annotation of /trunk/mkinitrd-magellan/busybox/e2fsprogs/old_e2fsprogs/ext2fs/bb_inode.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 532 - (hide annotations) (download)
Sat Sep 1 22:45:15 2007 UTC (16 years, 8 months ago) by niro
File MIME type: text/plain
File size: 6233 byte(s)
-import if magellan mkinitrd; it is a fork of redhats mkinitrd-5.0.8 with all magellan patches and features; deprecates magellan-src/mkinitrd

1 niro 532 /* vi: set sw=4 ts=4: */
2     /*
3     * bb_inode.c --- routines to update the bad block inode.
4     *
5     * WARNING: This routine modifies a lot of state in the filesystem; if
6     * this routine returns an error, the bad block inode may be in an
7     * inconsistent state.
8     *
9     * Copyright (C) 1994, 1995 Theodore Ts'o.
10     *
11     * %Begin-Header%
12     * This file may be redistributed under the terms of the GNU Public
13     * License.
14     * %End-Header%
15     */
16    
17     #include <stdio.h>
18     #include <string.h>
19     #if HAVE_UNISTD_H
20     #include <unistd.h>
21     #endif
22     #include <fcntl.h>
23     #include <time.h>
24     #if HAVE_SYS_STAT_H
25     #include <sys/stat.h>
26     #endif
27     #if HAVE_SYS_TYPES_H
28     #include <sys/types.h>
29     #endif
30    
31     #include "ext2_fs.h"
32     #include "ext2fs.h"
33    
34     struct set_badblock_record {
35     ext2_badblocks_iterate bb_iter;
36     int bad_block_count;
37     blk_t *ind_blocks;
38     int max_ind_blocks;
39     int ind_blocks_size;
40     int ind_blocks_ptr;
41     char *block_buf;
42     errcode_t err;
43     };
44    
45     static int set_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
46     e2_blkcnt_t blockcnt,
47     blk_t ref_block, int ref_offset,
48     void *priv_data);
49     static int clear_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
50     e2_blkcnt_t blockcnt,
51     blk_t ref_block, int ref_offset,
52     void *priv_data);
53    
54     /*
55     * Given a bad blocks bitmap, update the bad blocks inode to reflect
56     * the map.
57     */
58     errcode_t ext2fs_update_bb_inode(ext2_filsys fs, ext2_badblocks_list bb_list)
59     {
60     errcode_t retval;
61     struct set_badblock_record rec;
62     struct ext2_inode inode;
63    
64     EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
65    
66     if (!fs->block_map)
67     return EXT2_ET_NO_BLOCK_BITMAP;
68    
69     rec.bad_block_count = 0;
70     rec.ind_blocks_size = rec.ind_blocks_ptr = 0;
71     rec.max_ind_blocks = 10;
72     retval = ext2fs_get_mem(rec.max_ind_blocks * sizeof(blk_t),
73     &rec.ind_blocks);
74     if (retval)
75     return retval;
76     memset(rec.ind_blocks, 0, rec.max_ind_blocks * sizeof(blk_t));
77     retval = ext2fs_get_mem(fs->blocksize, &rec.block_buf);
78     if (retval)
79     goto cleanup;
80     memset(rec.block_buf, 0, fs->blocksize);
81     rec.err = 0;
82    
83     /*
84     * First clear the old bad blocks (while saving the indirect blocks)
85     */
86     retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO,
87     BLOCK_FLAG_DEPTH_TRAVERSE, 0,
88     clear_bad_block_proc, &rec);
89     if (retval)
90     goto cleanup;
91     if (rec.err) {
92     retval = rec.err;
93     goto cleanup;
94     }
95    
96     /*
97     * Now set the bad blocks!
98     *
99     * First, mark the bad blocks as used. This prevents a bad
100     * block from being used as an indirecto block for the bad
101     * block inode (!).
102     */
103     if (bb_list) {
104     retval = ext2fs_badblocks_list_iterate_begin(bb_list,
105     &rec.bb_iter);
106     if (retval)
107     goto cleanup;
108     retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO,
109     BLOCK_FLAG_APPEND, 0,
110     set_bad_block_proc, &rec);
111     ext2fs_badblocks_list_iterate_end(rec.bb_iter);
112     if (retval)
113     goto cleanup;
114     if (rec.err) {
115     retval = rec.err;
116     goto cleanup;
117     }
118     }
119    
120     /*
121     * Update the bad block inode's mod time and block count
122     * field.
123     */
124     retval = ext2fs_read_inode(fs, EXT2_BAD_INO, &inode);
125     if (retval)
126     goto cleanup;
127    
128     inode.i_atime = inode.i_mtime = time(0);
129     if (!inode.i_ctime)
130     inode.i_ctime = time(0);
131     inode.i_blocks = rec.bad_block_count * (fs->blocksize / 512);
132     inode.i_size = rec.bad_block_count * fs->blocksize;
133    
134     retval = ext2fs_write_inode(fs, EXT2_BAD_INO, &inode);
135     if (retval)
136     goto cleanup;
137    
138     cleanup:
139     ext2fs_free_mem(&rec.ind_blocks);
140     ext2fs_free_mem(&rec.block_buf);
141     return retval;
142     }
143    
144     /*
145     * Helper function for update_bb_inode()
146     *
147     * Clear the bad blocks in the bad block inode, while saving the
148     * indirect blocks.
149     */
150     #ifdef __TURBOC__
151     # pragma argsused
152     #endif
153     static int clear_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
154     e2_blkcnt_t blockcnt,
155     blk_t ref_block EXT2FS_ATTR((unused)),
156     int ref_offset EXT2FS_ATTR((unused)),
157     void *priv_data)
158     {
159     struct set_badblock_record *rec = (struct set_badblock_record *)
160     priv_data;
161     errcode_t retval;
162     unsigned long old_size;
163    
164     if (!*block_nr)
165     return 0;
166    
167     /*
168     * If the block number is outrageous, clear it and ignore it.
169     */
170     if (*block_nr >= fs->super->s_blocks_count ||
171     *block_nr < fs->super->s_first_data_block) {
172     *block_nr = 0;
173     return BLOCK_CHANGED;
174     }
175    
176     if (blockcnt < 0) {
177     if (rec->ind_blocks_size >= rec->max_ind_blocks) {
178     old_size = rec->max_ind_blocks * sizeof(blk_t);
179     rec->max_ind_blocks += 10;
180     retval = ext2fs_resize_mem(old_size,
181     rec->max_ind_blocks * sizeof(blk_t),
182     &rec->ind_blocks);
183     if (retval) {
184     rec->max_ind_blocks -= 10;
185     rec->err = retval;
186     return BLOCK_ABORT;
187     }
188     }
189     rec->ind_blocks[rec->ind_blocks_size++] = *block_nr;
190     }
191    
192     /*
193     * Mark the block as unused, and update accounting information
194     */
195     ext2fs_block_alloc_stats(fs, *block_nr, -1);
196    
197     *block_nr = 0;
198     return BLOCK_CHANGED;
199     }
200    
201    
202     /*
203     * Helper function for update_bb_inode()
204     *
205     * Set the block list in the bad block inode, using the supplied bitmap.
206     */
207     #ifdef __TURBOC__
208     #pragma argsused
209     #endif
210     static int set_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
211     e2_blkcnt_t blockcnt,
212     blk_t ref_block EXT2FS_ATTR((unused)),
213     int ref_offset EXT2FS_ATTR((unused)),
214     void *priv_data)
215     {
216     struct set_badblock_record *rec = (struct set_badblock_record *)
217     priv_data;
218     errcode_t retval;
219     blk_t blk;
220    
221     if (blockcnt >= 0) {
222     /*
223     * Get the next bad block.
224     */
225     if (!ext2fs_badblocks_list_iterate(rec->bb_iter, &blk))
226     return BLOCK_ABORT;
227     rec->bad_block_count++;
228     } else {
229     /*
230     * An indirect block; fetch a block from the
231     * previously used indirect block list. The block
232     * most be not marked as used; if so, get another one.
233     * If we run out of reserved indirect blocks, allocate
234     * a new one.
235     */
236     retry:
237     if (rec->ind_blocks_ptr < rec->ind_blocks_size) {
238     blk = rec->ind_blocks[rec->ind_blocks_ptr++];
239     if (ext2fs_test_block_bitmap(fs->block_map, blk))
240     goto retry;
241     } else {
242     retval = ext2fs_new_block(fs, 0, 0, &blk);
243     if (retval) {
244     rec->err = retval;
245     return BLOCK_ABORT;
246     }
247     }
248     retval = io_channel_write_blk(fs->io, blk, 1, rec->block_buf);
249     if (retval) {
250     rec->err = retval;
251     return BLOCK_ABORT;
252     }
253     }
254    
255     /*
256     * Update block counts
257     */
258     ext2fs_block_alloc_stats(fs, blk, +1);
259    
260     *block_nr = blk;
261     return BLOCK_CHANGED;
262     }
263    
264    
265    
266    
267    
268