diff options
Diffstat (limited to 'fs/reiserfs/bitmap.c')
-rw-r--r-- | fs/reiserfs/bitmap.c | 60 |
1 files changed, 36 insertions, 24 deletions
diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c index 1022347a211f..44d9410e9d6a 100644 --- a/fs/reiserfs/bitmap.c +++ b/fs/reiserfs/bitmap.c | |||
@@ -59,6 +59,7 @@ static inline void get_bit_address(struct super_block *s, | |||
59 | int is_reusable(struct super_block *s, b_blocknr_t block, int bit_value) | 59 | int is_reusable(struct super_block *s, b_blocknr_t block, int bit_value) |
60 | { | 60 | { |
61 | int bmap, offset; | 61 | int bmap, offset; |
62 | struct buffer_head *bh; | ||
62 | 63 | ||
63 | if (block == 0 || block >= SB_BLOCK_COUNT(s)) { | 64 | if (block == 0 || block >= SB_BLOCK_COUNT(s)) { |
64 | reiserfs_warning(s, | 65 | reiserfs_warning(s, |
@@ -96,20 +97,21 @@ int is_reusable(struct super_block *s, b_blocknr_t block, int bit_value) | |||
96 | return 0; | 97 | return 0; |
97 | } | 98 | } |
98 | 99 | ||
99 | if ((bit_value == 0 && | 100 | bh = SB_AP_BITMAP(s)[bmap].bh; |
100 | reiserfs_test_le_bit(offset, SB_AP_BITMAP(s)[bmap].bh->b_data)) || | 101 | get_bh(bh); |
101 | (bit_value == 1 && | 102 | |
102 | reiserfs_test_le_bit(offset, SB_AP_BITMAP(s)[bmap].bh->b_data) == 0)) { | 103 | if ((bit_value == 0 && reiserfs_test_le_bit(offset, bh->b_data)) || |
104 | (bit_value == 1 && reiserfs_test_le_bit(offset, bh->b_data) == 0)) { | ||
103 | reiserfs_warning(s, | 105 | reiserfs_warning(s, |
104 | "vs-4040: is_reusable: corresponding bit of block %lu does not " | 106 | "vs-4040: is_reusable: corresponding bit of block %lu does not " |
105 | "match required value (bmap==%d, offset==%d) test_bit==%d", | 107 | "match required value (bmap==%d, offset==%d) test_bit==%d", |
106 | block, bmap, offset, reiserfs_test_le_bit(offset, | 108 | block, bmap, offset, |
107 | SB_AP_BITMAP | 109 | reiserfs_test_le_bit(offset, bh->b_data)); |
108 | (s)[bmap].bh-> | ||
109 | b_data)); | ||
110 | 110 | ||
111 | brelse(bh); | ||
111 | return 0; | 112 | return 0; |
112 | } | 113 | } |
114 | brelse(bh); | ||
113 | 115 | ||
114 | if (bit_value == 0 && block == SB_ROOT_BLOCK(s)) { | 116 | if (bit_value == 0 && block == SB_ROOT_BLOCK(s)) { |
115 | reiserfs_warning(s, | 117 | reiserfs_warning(s, |
@@ -151,6 +153,7 @@ static int scan_bitmap_block(struct reiserfs_transaction_handle *th, | |||
151 | { | 153 | { |
152 | struct super_block *s = th->t_super; | 154 | struct super_block *s = th->t_super; |
153 | struct reiserfs_bitmap_info *bi = &SB_AP_BITMAP(s)[bmap_n]; | 155 | struct reiserfs_bitmap_info *bi = &SB_AP_BITMAP(s)[bmap_n]; |
156 | struct buffer_head *bh; | ||
154 | int end, next; | 157 | int end, next; |
155 | int org = *beg; | 158 | int org = *beg; |
156 | 159 | ||
@@ -169,22 +172,28 @@ static int scan_bitmap_block(struct reiserfs_transaction_handle *th, | |||
169 | bmap_n); | 172 | bmap_n); |
170 | return 0; | 173 | return 0; |
171 | } | 174 | } |
172 | if (buffer_locked(bi->bh)) { | 175 | bh = bi->bh; |
176 | get_bh(bh); | ||
177 | |||
178 | if (buffer_locked(bh)) { | ||
173 | PROC_INFO_INC(s, scan_bitmap.wait); | 179 | PROC_INFO_INC(s, scan_bitmap.wait); |
174 | __wait_on_buffer(bi->bh); | 180 | __wait_on_buffer(bh); |
175 | } | 181 | } |
176 | 182 | ||
177 | while (1) { | 183 | while (1) { |
178 | cont: | 184 | cont: |
179 | if (bi->free_count < min) | 185 | if (bi->free_count < min) { |
186 | brelse(bh); | ||
180 | return 0; // No free blocks in this bitmap | 187 | return 0; // No free blocks in this bitmap |
188 | } | ||
181 | 189 | ||
182 | /* search for a first zero bit -- beggining of a window */ | 190 | /* search for a first zero bit -- beggining of a window */ |
183 | *beg = reiserfs_find_next_zero_le_bit | 191 | *beg = reiserfs_find_next_zero_le_bit |
184 | ((unsigned long *)(bi->bh->b_data), boundary, *beg); | 192 | ((unsigned long *)(bh->b_data), boundary, *beg); |
185 | 193 | ||
186 | if (*beg + min > boundary) { /* search for a zero bit fails or the rest of bitmap block | 194 | if (*beg + min > boundary) { /* search for a zero bit fails or the rest of bitmap block |
187 | * cannot contain a zero window of minimum size */ | 195 | * cannot contain a zero window of minimum size */ |
196 | brelse(bh); | ||
188 | return 0; | 197 | return 0; |
189 | } | 198 | } |
190 | 199 | ||
@@ -193,7 +202,7 @@ static int scan_bitmap_block(struct reiserfs_transaction_handle *th, | |||
193 | /* first zero bit found; we check next bits */ | 202 | /* first zero bit found; we check next bits */ |
194 | for (end = *beg + 1;; end++) { | 203 | for (end = *beg + 1;; end++) { |
195 | if (end >= *beg + max || end >= boundary | 204 | if (end >= *beg + max || end >= boundary |
196 | || reiserfs_test_le_bit(end, bi->bh->b_data)) { | 205 | || reiserfs_test_le_bit(end, bh->b_data)) { |
197 | next = end; | 206 | next = end; |
198 | break; | 207 | break; |
199 | } | 208 | } |
@@ -207,12 +216,12 @@ static int scan_bitmap_block(struct reiserfs_transaction_handle *th, | |||
207 | * (end) points to one bit after the window end */ | 216 | * (end) points to one bit after the window end */ |
208 | if (end - *beg >= min) { /* it seems we have found window of proper size */ | 217 | if (end - *beg >= min) { /* it seems we have found window of proper size */ |
209 | int i; | 218 | int i; |
210 | reiserfs_prepare_for_journal(s, bi->bh, 1); | 219 | reiserfs_prepare_for_journal(s, bh, 1); |
211 | /* try to set all blocks used checking are they still free */ | 220 | /* try to set all blocks used checking are they still free */ |
212 | for (i = *beg; i < end; i++) { | 221 | for (i = *beg; i < end; i++) { |
213 | /* It seems that we should not check in journal again. */ | 222 | /* It seems that we should not check in journal again. */ |
214 | if (reiserfs_test_and_set_le_bit | 223 | if (reiserfs_test_and_set_le_bit |
215 | (i, bi->bh->b_data)) { | 224 | (i, bh->b_data)) { |
216 | /* bit was set by another process | 225 | /* bit was set by another process |
217 | * while we slept in prepare_for_journal() */ | 226 | * while we slept in prepare_for_journal() */ |
218 | PROC_INFO_INC(s, scan_bitmap.stolen); | 227 | PROC_INFO_INC(s, scan_bitmap.stolen); |
@@ -224,17 +233,16 @@ static int scan_bitmap_block(struct reiserfs_transaction_handle *th, | |||
224 | /* otherwise we clear all bit were set ... */ | 233 | /* otherwise we clear all bit were set ... */ |
225 | while (--i >= *beg) | 234 | while (--i >= *beg) |
226 | reiserfs_test_and_clear_le_bit | 235 | reiserfs_test_and_clear_le_bit |
227 | (i, bi->bh->b_data); | 236 | (i, bh->b_data); |
228 | reiserfs_restore_prepared_buffer(s, | 237 | reiserfs_restore_prepared_buffer(s, bh); |
229 | bi-> | ||
230 | bh); | ||
231 | *beg = org; | 238 | *beg = org; |
232 | /* ... and search again in current block from beginning */ | 239 | /* ... and search again in current block from beginning */ |
233 | goto cont; | 240 | goto cont; |
234 | } | 241 | } |
235 | } | 242 | } |
236 | bi->free_count -= (end - *beg); | 243 | bi->free_count -= (end - *beg); |
237 | journal_mark_dirty(th, s, bi->bh); | 244 | journal_mark_dirty(th, s, bh); |
245 | brelse(bh); | ||
238 | 246 | ||
239 | /* free block count calculation */ | 247 | /* free block count calculation */ |
240 | reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), | 248 | reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), |
@@ -383,7 +391,7 @@ static void _reiserfs_free_block(struct reiserfs_transaction_handle *th, | |||
383 | { | 391 | { |
384 | struct super_block *s = th->t_super; | 392 | struct super_block *s = th->t_super; |
385 | struct reiserfs_super_block *rs; | 393 | struct reiserfs_super_block *rs; |
386 | struct buffer_head *sbh; | 394 | struct buffer_head *sbh, *bmbh; |
387 | struct reiserfs_bitmap_info *apbi; | 395 | struct reiserfs_bitmap_info *apbi; |
388 | int nr, offset; | 396 | int nr, offset; |
389 | 397 | ||
@@ -404,16 +412,20 @@ static void _reiserfs_free_block(struct reiserfs_transaction_handle *th, | |||
404 | return; | 412 | return; |
405 | } | 413 | } |
406 | 414 | ||
407 | reiserfs_prepare_for_journal(s, apbi[nr].bh, 1); | 415 | bmbh = apbi[nr].bh; |
416 | get_bh(bmbh); | ||
417 | |||
418 | reiserfs_prepare_for_journal(s, bmbh, 1); | ||
408 | 419 | ||
409 | /* clear bit for the given block in bit map */ | 420 | /* clear bit for the given block in bit map */ |
410 | if (!reiserfs_test_and_clear_le_bit(offset, apbi[nr].bh->b_data)) { | 421 | if (!reiserfs_test_and_clear_le_bit(offset, bmbh->b_data)) { |
411 | reiserfs_warning(s, "vs-4080: reiserfs_free_block: " | 422 | reiserfs_warning(s, "vs-4080: reiserfs_free_block: " |
412 | "free_block (%s:%lu)[dev:blocknr]: bit already cleared", | 423 | "free_block (%s:%lu)[dev:blocknr]: bit already cleared", |
413 | reiserfs_bdevname(s), block); | 424 | reiserfs_bdevname(s), block); |
414 | } | 425 | } |
415 | apbi[nr].free_count++; | 426 | apbi[nr].free_count++; |
416 | journal_mark_dirty(th, s, apbi[nr].bh); | 427 | journal_mark_dirty(th, s, bmbh); |
428 | brelse(bmbh); | ||
417 | 429 | ||
418 | reiserfs_prepare_for_journal(s, sbh, 1); | 430 | reiserfs_prepare_for_journal(s, sbh, 1); |
419 | /* update super block */ | 431 | /* update super block */ |