diff options
Diffstat (limited to 'fs/reiserfs/bitmap.c')
-rw-r--r-- | fs/reiserfs/bitmap.c | 216 |
1 files changed, 148 insertions, 68 deletions
diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c index 4a7dbdee1b6d..1bfae42117ca 100644 --- a/fs/reiserfs/bitmap.c +++ b/fs/reiserfs/bitmap.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <linux/buffer_head.h> | 9 | #include <linux/buffer_head.h> |
10 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
11 | #include <linux/pagemap.h> | 11 | #include <linux/pagemap.h> |
12 | #include <linux/vmalloc.h> | ||
12 | #include <linux/reiserfs_fs_sb.h> | 13 | #include <linux/reiserfs_fs_sb.h> |
13 | #include <linux/reiserfs_fs_i.h> | 14 | #include <linux/reiserfs_fs_i.h> |
14 | #include <linux/quotaops.h> | 15 | #include <linux/quotaops.h> |
@@ -50,16 +51,15 @@ static inline void get_bit_address(struct super_block *s, | |||
50 | { | 51 | { |
51 | /* It is in the bitmap block number equal to the block | 52 | /* It is in the bitmap block number equal to the block |
52 | * number divided by the number of bits in a block. */ | 53 | * number divided by the number of bits in a block. */ |
53 | *bmap_nr = block / (s->s_blocksize << 3); | 54 | *bmap_nr = block >> (s->s_blocksize_bits + 3); |
54 | /* Within that bitmap block it is located at bit offset *offset. */ | 55 | /* Within that bitmap block it is located at bit offset *offset. */ |
55 | *offset = block & ((s->s_blocksize << 3) - 1); | 56 | *offset = block & ((s->s_blocksize << 3) - 1); |
56 | return; | ||
57 | } | 57 | } |
58 | 58 | ||
59 | #ifdef CONFIG_REISERFS_CHECK | 59 | #ifdef CONFIG_REISERFS_CHECK |
60 | int is_reusable(struct super_block *s, b_blocknr_t block, int bit_value) | 60 | int is_reusable(struct super_block *s, b_blocknr_t block, int bit_value) |
61 | { | 61 | { |
62 | int i, j; | 62 | int bmap, offset; |
63 | 63 | ||
64 | if (block == 0 || block >= SB_BLOCK_COUNT(s)) { | 64 | if (block == 0 || block >= SB_BLOCK_COUNT(s)) { |
65 | reiserfs_warning(s, | 65 | reiserfs_warning(s, |
@@ -68,36 +68,32 @@ int is_reusable(struct super_block *s, b_blocknr_t block, int bit_value) | |||
68 | return 0; | 68 | return 0; |
69 | } | 69 | } |
70 | 70 | ||
71 | /* it can't be one of the bitmap blocks */ | 71 | get_bit_address(s, block, &bmap, &offset); |
72 | for (i = 0; i < SB_BMAP_NR(s); i++) | 72 | |
73 | if (block == SB_AP_BITMAP(s)[i].bh->b_blocknr) { | 73 | /* Old format filesystem? Unlikely, but the bitmaps are all up front so |
74 | * we need to account for it. */ | ||
75 | if (unlikely(test_bit(REISERFS_OLD_FORMAT, | ||
76 | &(REISERFS_SB(s)->s_properties)))) { | ||
77 | b_blocknr_t bmap1 = REISERFS_SB(s)->s_sbh->b_blocknr + 1; | ||
78 | if (block >= bmap1 && block <= bmap1 + SB_BMAP_NR(s)) { | ||
79 | reiserfs_warning(s, "vs: 4019: is_reusable: " | ||
80 | "bitmap block %lu(%u) can't be freed or reused", | ||
81 | block, SB_BMAP_NR(s)); | ||
82 | return 0; | ||
83 | } | ||
84 | } else { | ||
85 | if (offset == 0) { | ||
74 | reiserfs_warning(s, "vs: 4020: is_reusable: " | 86 | reiserfs_warning(s, "vs: 4020: is_reusable: " |
75 | "bitmap block %lu(%u) can't be freed or reused", | 87 | "bitmap block %lu(%u) can't be freed or reused", |
76 | block, SB_BMAP_NR(s)); | 88 | block, SB_BMAP_NR(s)); |
77 | return 0; | 89 | return 0; |
78 | } | 90 | } |
79 | |||
80 | get_bit_address(s, block, &i, &j); | ||
81 | |||
82 | if (i >= SB_BMAP_NR(s)) { | ||
83 | reiserfs_warning(s, | ||
84 | "vs-4030: is_reusable: there is no so many bitmap blocks: " | ||
85 | "block=%lu, bitmap_nr=%d", block, i); | ||
86 | return 0; | ||
87 | } | 91 | } |
88 | 92 | ||
89 | if ((bit_value == 0 && | 93 | if (bmap >= SB_BMAP_NR(s)) { |
90 | reiserfs_test_le_bit(j, SB_AP_BITMAP(s)[i].bh->b_data)) || | ||
91 | (bit_value == 1 && | ||
92 | reiserfs_test_le_bit(j, SB_AP_BITMAP(s)[i].bh->b_data) == 0)) { | ||
93 | reiserfs_warning(s, | 94 | reiserfs_warning(s, |
94 | "vs-4040: is_reusable: corresponding bit of block %lu does not " | 95 | "vs-4030: is_reusable: there is no so many bitmap blocks: " |
95 | "match required value (i==%d, j==%d) test_bit==%d", | 96 | "block=%lu, bitmap_nr=%d", block, bmap); |
96 | block, i, j, reiserfs_test_le_bit(j, | ||
97 | SB_AP_BITMAP | ||
98 | (s)[i].bh-> | ||
99 | b_data)); | ||
100 | |||
101 | return 0; | 97 | return 0; |
102 | } | 98 | } |
103 | 99 | ||
@@ -141,6 +137,7 @@ static int scan_bitmap_block(struct reiserfs_transaction_handle *th, | |||
141 | { | 137 | { |
142 | struct super_block *s = th->t_super; | 138 | struct super_block *s = th->t_super; |
143 | struct reiserfs_bitmap_info *bi = &SB_AP_BITMAP(s)[bmap_n]; | 139 | struct reiserfs_bitmap_info *bi = &SB_AP_BITMAP(s)[bmap_n]; |
140 | struct buffer_head *bh; | ||
144 | int end, next; | 141 | int end, next; |
145 | int org = *beg; | 142 | int org = *beg; |
146 | 143 | ||
@@ -159,22 +156,25 @@ static int scan_bitmap_block(struct reiserfs_transaction_handle *th, | |||
159 | bmap_n); | 156 | bmap_n); |
160 | return 0; | 157 | return 0; |
161 | } | 158 | } |
162 | if (buffer_locked(bi->bh)) { | 159 | |
163 | PROC_INFO_INC(s, scan_bitmap.wait); | 160 | bh = reiserfs_read_bitmap_block(s, bmap_n); |
164 | __wait_on_buffer(bi->bh); | 161 | if (bh == NULL) |
165 | } | 162 | return 0; |
166 | 163 | ||
167 | while (1) { | 164 | while (1) { |
168 | cont: | 165 | cont: |
169 | if (bi->free_count < min) | 166 | if (bi->free_count < min) { |
167 | brelse(bh); | ||
170 | return 0; // No free blocks in this bitmap | 168 | return 0; // No free blocks in this bitmap |
169 | } | ||
171 | 170 | ||
172 | /* search for a first zero bit -- beggining of a window */ | 171 | /* search for a first zero bit -- beggining of a window */ |
173 | *beg = reiserfs_find_next_zero_le_bit | 172 | *beg = reiserfs_find_next_zero_le_bit |
174 | ((unsigned long *)(bi->bh->b_data), boundary, *beg); | 173 | ((unsigned long *)(bh->b_data), boundary, *beg); |
175 | 174 | ||
176 | if (*beg + min > boundary) { /* search for a zero bit fails or the rest of bitmap block | 175 | if (*beg + min > boundary) { /* search for a zero bit fails or the rest of bitmap block |
177 | * cannot contain a zero window of minimum size */ | 176 | * cannot contain a zero window of minimum size */ |
177 | brelse(bh); | ||
178 | return 0; | 178 | return 0; |
179 | } | 179 | } |
180 | 180 | ||
@@ -183,7 +183,7 @@ static int scan_bitmap_block(struct reiserfs_transaction_handle *th, | |||
183 | /* first zero bit found; we check next bits */ | 183 | /* first zero bit found; we check next bits */ |
184 | for (end = *beg + 1;; end++) { | 184 | for (end = *beg + 1;; end++) { |
185 | if (end >= *beg + max || end >= boundary | 185 | if (end >= *beg + max || end >= boundary |
186 | || reiserfs_test_le_bit(end, bi->bh->b_data)) { | 186 | || reiserfs_test_le_bit(end, bh->b_data)) { |
187 | next = end; | 187 | next = end; |
188 | break; | 188 | break; |
189 | } | 189 | } |
@@ -197,12 +197,12 @@ static int scan_bitmap_block(struct reiserfs_transaction_handle *th, | |||
197 | * (end) points to one bit after the window end */ | 197 | * (end) points to one bit after the window end */ |
198 | if (end - *beg >= min) { /* it seems we have found window of proper size */ | 198 | if (end - *beg >= min) { /* it seems we have found window of proper size */ |
199 | int i; | 199 | int i; |
200 | reiserfs_prepare_for_journal(s, bi->bh, 1); | 200 | reiserfs_prepare_for_journal(s, bh, 1); |
201 | /* try to set all blocks used checking are they still free */ | 201 | /* try to set all blocks used checking are they still free */ |
202 | for (i = *beg; i < end; i++) { | 202 | for (i = *beg; i < end; i++) { |
203 | /* It seems that we should not check in journal again. */ | 203 | /* It seems that we should not check in journal again. */ |
204 | if (reiserfs_test_and_set_le_bit | 204 | if (reiserfs_test_and_set_le_bit |
205 | (i, bi->bh->b_data)) { | 205 | (i, bh->b_data)) { |
206 | /* bit was set by another process | 206 | /* bit was set by another process |
207 | * while we slept in prepare_for_journal() */ | 207 | * while we slept in prepare_for_journal() */ |
208 | PROC_INFO_INC(s, scan_bitmap.stolen); | 208 | PROC_INFO_INC(s, scan_bitmap.stolen); |
@@ -214,17 +214,16 @@ static int scan_bitmap_block(struct reiserfs_transaction_handle *th, | |||
214 | /* otherwise we clear all bit were set ... */ | 214 | /* otherwise we clear all bit were set ... */ |
215 | while (--i >= *beg) | 215 | while (--i >= *beg) |
216 | reiserfs_test_and_clear_le_bit | 216 | reiserfs_test_and_clear_le_bit |
217 | (i, bi->bh->b_data); | 217 | (i, bh->b_data); |
218 | reiserfs_restore_prepared_buffer(s, | 218 | reiserfs_restore_prepared_buffer(s, bh); |
219 | bi-> | ||
220 | bh); | ||
221 | *beg = org; | 219 | *beg = org; |
222 | /* ... and search again in current block from beginning */ | 220 | /* ... and search again in current block from beginning */ |
223 | goto cont; | 221 | goto cont; |
224 | } | 222 | } |
225 | } | 223 | } |
226 | bi->free_count -= (end - *beg); | 224 | bi->free_count -= (end - *beg); |
227 | journal_mark_dirty(th, s, bi->bh); | 225 | journal_mark_dirty(th, s, bh); |
226 | brelse(bh); | ||
228 | 227 | ||
229 | /* free block count calculation */ | 228 | /* free block count calculation */ |
230 | reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), | 229 | reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), |
@@ -266,9 +265,20 @@ static int bmap_hash_id(struct super_block *s, u32 id) | |||
266 | */ | 265 | */ |
267 | static inline int block_group_used(struct super_block *s, u32 id) | 266 | static inline int block_group_used(struct super_block *s, u32 id) |
268 | { | 267 | { |
269 | int bm; | 268 | int bm = bmap_hash_id(s, id); |
270 | bm = bmap_hash_id(s, id); | 269 | struct reiserfs_bitmap_info *info = &SB_AP_BITMAP(s)[bm]; |
271 | if (SB_AP_BITMAP(s)[bm].free_count > ((s->s_blocksize << 3) * 60 / 100)) { | 270 | |
271 | /* If we don't have cached information on this bitmap block, we're | ||
272 | * going to have to load it later anyway. Loading it here allows us | ||
273 | * to make a better decision. This favors long-term performace gain | ||
274 | * with a better on-disk layout vs. a short term gain of skipping the | ||
275 | * read and potentially having a bad placement. */ | ||
276 | if (info->first_zero_hint == 0) { | ||
277 | struct buffer_head *bh = reiserfs_read_bitmap_block(s, bm); | ||
278 | brelse(bh); | ||
279 | } | ||
280 | |||
281 | if (info->free_count > ((s->s_blocksize << 3) * 60 / 100)) { | ||
272 | return 0; | 282 | return 0; |
273 | } | 283 | } |
274 | return 1; | 284 | return 1; |
@@ -373,7 +383,7 @@ static void _reiserfs_free_block(struct reiserfs_transaction_handle *th, | |||
373 | { | 383 | { |
374 | struct super_block *s = th->t_super; | 384 | struct super_block *s = th->t_super; |
375 | struct reiserfs_super_block *rs; | 385 | struct reiserfs_super_block *rs; |
376 | struct buffer_head *sbh; | 386 | struct buffer_head *sbh, *bmbh; |
377 | struct reiserfs_bitmap_info *apbi; | 387 | struct reiserfs_bitmap_info *apbi; |
378 | int nr, offset; | 388 | int nr, offset; |
379 | 389 | ||
@@ -394,16 +404,21 @@ static void _reiserfs_free_block(struct reiserfs_transaction_handle *th, | |||
394 | return; | 404 | return; |
395 | } | 405 | } |
396 | 406 | ||
397 | reiserfs_prepare_for_journal(s, apbi[nr].bh, 1); | 407 | bmbh = reiserfs_read_bitmap_block(s, nr); |
408 | if (!bmbh) | ||
409 | return; | ||
410 | |||
411 | reiserfs_prepare_for_journal(s, bmbh, 1); | ||
398 | 412 | ||
399 | /* clear bit for the given block in bit map */ | 413 | /* clear bit for the given block in bit map */ |
400 | if (!reiserfs_test_and_clear_le_bit(offset, apbi[nr].bh->b_data)) { | 414 | if (!reiserfs_test_and_clear_le_bit(offset, bmbh->b_data)) { |
401 | reiserfs_warning(s, "vs-4080: reiserfs_free_block: " | 415 | reiserfs_warning(s, "vs-4080: reiserfs_free_block: " |
402 | "free_block (%s:%lu)[dev:blocknr]: bit already cleared", | 416 | "free_block (%s:%lu)[dev:blocknr]: bit already cleared", |
403 | reiserfs_bdevname(s), block); | 417 | reiserfs_bdevname(s), block); |
404 | } | 418 | } |
405 | apbi[nr].free_count++; | 419 | apbi[nr].free_count++; |
406 | journal_mark_dirty(th, s, apbi[nr].bh); | 420 | journal_mark_dirty(th, s, bmbh); |
421 | brelse(bmbh); | ||
407 | 422 | ||
408 | reiserfs_prepare_for_journal(s, sbh, 1); | 423 | reiserfs_prepare_for_journal(s, sbh, 1); |
409 | /* update super block */ | 424 | /* update super block */ |
@@ -1019,7 +1034,6 @@ static inline int blocknrs_and_prealloc_arrays_from_search_start | |||
1019 | b_blocknr_t finish = SB_BLOCK_COUNT(s) - 1; | 1034 | b_blocknr_t finish = SB_BLOCK_COUNT(s) - 1; |
1020 | int passno = 0; | 1035 | int passno = 0; |
1021 | int nr_allocated = 0; | 1036 | int nr_allocated = 0; |
1022 | int bigalloc = 0; | ||
1023 | 1037 | ||
1024 | determine_prealloc_size(hint); | 1038 | determine_prealloc_size(hint); |
1025 | if (!hint->formatted_node) { | 1039 | if (!hint->formatted_node) { |
@@ -1046,28 +1060,9 @@ static inline int blocknrs_and_prealloc_arrays_from_search_start | |||
1046 | hint->preallocate = hint->prealloc_size = 0; | 1060 | hint->preallocate = hint->prealloc_size = 0; |
1047 | } | 1061 | } |
1048 | /* for unformatted nodes, force large allocations */ | 1062 | /* for unformatted nodes, force large allocations */ |
1049 | bigalloc = amount_needed; | ||
1050 | } | 1063 | } |
1051 | 1064 | ||
1052 | do { | 1065 | do { |
1053 | /* in bigalloc mode, nr_allocated should stay zero until | ||
1054 | * the entire allocation is filled | ||
1055 | */ | ||
1056 | if (unlikely(bigalloc && nr_allocated)) { | ||
1057 | reiserfs_warning(s, "bigalloc is %d, nr_allocated %d\n", | ||
1058 | bigalloc, nr_allocated); | ||
1059 | /* reset things to a sane value */ | ||
1060 | bigalloc = amount_needed - nr_allocated; | ||
1061 | } | ||
1062 | /* | ||
1063 | * try pass 0 and pass 1 looking for a nice big | ||
1064 | * contiguous allocation. Then reset and look | ||
1065 | * for anything you can find. | ||
1066 | */ | ||
1067 | if (passno == 2 && bigalloc) { | ||
1068 | passno = 0; | ||
1069 | bigalloc = 0; | ||
1070 | } | ||
1071 | switch (passno++) { | 1066 | switch (passno++) { |
1072 | case 0: /* Search from hint->search_start to end of disk */ | 1067 | case 0: /* Search from hint->search_start to end of disk */ |
1073 | start = hint->search_start; | 1068 | start = hint->search_start; |
@@ -1105,8 +1100,7 @@ static inline int blocknrs_and_prealloc_arrays_from_search_start | |||
1105 | new_blocknrs + | 1100 | new_blocknrs + |
1106 | nr_allocated, | 1101 | nr_allocated, |
1107 | start, finish, | 1102 | start, finish, |
1108 | bigalloc ? | 1103 | 1, |
1109 | bigalloc : 1, | ||
1110 | amount_needed - | 1104 | amount_needed - |
1111 | nr_allocated, | 1105 | nr_allocated, |
1112 | hint-> | 1106 | hint-> |
@@ -1263,3 +1257,89 @@ int reiserfs_can_fit_pages(struct super_block *sb /* superblock of filesystem | |||
1263 | 1257 | ||
1264 | return space > 0 ? space : 0; | 1258 | return space > 0 ? space : 0; |
1265 | } | 1259 | } |
1260 | |||
1261 | void reiserfs_cache_bitmap_metadata(struct super_block *sb, | ||
1262 | struct buffer_head *bh, | ||
1263 | struct reiserfs_bitmap_info *info) | ||
1264 | { | ||
1265 | unsigned long *cur = (unsigned long *)(bh->b_data + bh->b_size); | ||
1266 | |||
1267 | info->first_zero_hint = 1 << (sb->s_blocksize_bits + 3); | ||
1268 | |||
1269 | while (--cur >= (unsigned long *)bh->b_data) { | ||
1270 | int base = ((char *)cur - bh->b_data) << 3; | ||
1271 | |||
1272 | /* 0 and ~0 are special, we can optimize for them */ | ||
1273 | if (*cur == 0) { | ||
1274 | info->first_zero_hint = base; | ||
1275 | info->free_count += BITS_PER_LONG; | ||
1276 | } else if (*cur != ~0L) { /* A mix, investigate */ | ||
1277 | int b; | ||
1278 | for (b = BITS_PER_LONG - 1; b >= 0; b--) { | ||
1279 | if (!reiserfs_test_le_bit(b, cur)) { | ||
1280 | info->first_zero_hint = base + b; | ||
1281 | info->free_count++; | ||
1282 | } | ||
1283 | } | ||
1284 | } | ||
1285 | } | ||
1286 | /* The first bit must ALWAYS be 1 */ | ||
1287 | BUG_ON(info->first_zero_hint == 0); | ||
1288 | } | ||
1289 | |||
1290 | struct buffer_head *reiserfs_read_bitmap_block(struct super_block *sb, | ||
1291 | unsigned int bitmap) | ||
1292 | { | ||
1293 | b_blocknr_t block = (sb->s_blocksize << 3) * bitmap; | ||
1294 | struct reiserfs_bitmap_info *info = SB_AP_BITMAP(sb) + bitmap; | ||
1295 | struct buffer_head *bh; | ||
1296 | |||
1297 | /* Way old format filesystems had the bitmaps packed up front. | ||
1298 | * I doubt there are any of these left, but just in case... */ | ||
1299 | if (unlikely(test_bit(REISERFS_OLD_FORMAT, | ||
1300 | &(REISERFS_SB(sb)->s_properties)))) | ||
1301 | block = REISERFS_SB(sb)->s_sbh->b_blocknr + 1 + bitmap; | ||
1302 | else if (bitmap == 0) | ||
1303 | block = (REISERFS_DISK_OFFSET_IN_BYTES >> sb->s_blocksize_bits) + 1; | ||
1304 | |||
1305 | bh = sb_bread(sb, block); | ||
1306 | if (bh == NULL) | ||
1307 | reiserfs_warning(sb, "sh-2029: %s: bitmap block (#%lu) " | ||
1308 | "reading failed", __FUNCTION__, bh->b_blocknr); | ||
1309 | else { | ||
1310 | if (buffer_locked(bh)) { | ||
1311 | PROC_INFO_INC(sb, scan_bitmap.wait); | ||
1312 | __wait_on_buffer(bh); | ||
1313 | } | ||
1314 | BUG_ON(!buffer_uptodate(bh)); | ||
1315 | BUG_ON(atomic_read(&bh->b_count) == 0); | ||
1316 | |||
1317 | if (info->first_zero_hint == 0) | ||
1318 | reiserfs_cache_bitmap_metadata(sb, bh, info); | ||
1319 | } | ||
1320 | |||
1321 | return bh; | ||
1322 | } | ||
1323 | |||
1324 | int reiserfs_init_bitmap_cache(struct super_block *sb) | ||
1325 | { | ||
1326 | struct reiserfs_bitmap_info *bitmap; | ||
1327 | |||
1328 | bitmap = vmalloc(sizeof (*bitmap) * SB_BMAP_NR(sb)); | ||
1329 | if (bitmap == NULL) | ||
1330 | return -ENOMEM; | ||
1331 | |||
1332 | memset(bitmap, 0, sizeof (*bitmap) * SB_BMAP_NR(sb)); | ||
1333 | |||
1334 | SB_AP_BITMAP(sb) = bitmap; | ||
1335 | |||
1336 | return 0; | ||
1337 | } | ||
1338 | |||
1339 | void reiserfs_free_bitmap_cache(struct super_block *sb) | ||
1340 | { | ||
1341 | if (SB_AP_BITMAP(sb)) { | ||
1342 | vfree(SB_AP_BITMAP(sb)); | ||
1343 | SB_AP_BITMAP(sb) = NULL; | ||
1344 | } | ||
1345 | } | ||