aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Mahoney <jeffm@suse.com>2006-10-01 02:28:43 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-01 03:39:27 -0400
commit6f01046b35d940079822827498a7dd6d3eec8c6b (patch)
treee65426389691c9d3e7d4f29da73725d15ee8e2f6
parent0b3dc17bc0c0997bde9f5d7691ec0cae24258cf7 (diff)
[PATCH] reiserfs: reorganize bitmap loading functions
This patch moves the bitmap loading code from super.c to bitmap.c The code is also restructured somewhat. The only difference between new format bitmaps and old format bitmaps is where they are. That's a two liner before loading the block to use the correct one. There's no need for an entirely separate code path. The load path is generally the same, with the pattern being to throw out a bunch of requests and then wait for them, then cache the metadata from the contents. Again, like the previous patches, the purpose is to set up for later ones. Update: There was a bug in the previously posted version of this that resulted in corruption. The problem was that bitmap 0 on new format file systems must be treated specially, and wasn't. A stupid bug with an easy fix. This is hopefully the last fix for the disaster that is the reiserfs bitmap patch set. If a bitmap block was full, first_zero_hint would end up at zero since it would never be changed from it's zeroed out value. This just sets it beyond the end of the bitmap block. If any bits are freed, it will be reset to a valid bit. When info->free_count = 0, then we already know it's full. Signed-off-by: Jeff Mahoney <jeffm@suse.com> Cc: <reiserfs-dev@namesys.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--fs/reiserfs/bitmap.c88
-rw-r--r--fs/reiserfs/resize.c1
-rw-r--r--fs/reiserfs/super.c114
-rw-r--r--include/linux/reiserfs_fs.h4
4 files changed, 94 insertions, 113 deletions
diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c
index 44d9410e9d6a..abdd6d9c4558 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>
@@ -1285,3 +1286,90 @@ int reiserfs_can_fit_pages(struct super_block *sb /* superblock of filesystem
1285 1286
1286 return space > 0 ? space : 0; 1287 return space > 0 ? space : 0;
1287} 1288}
1289
1290void reiserfs_cache_bitmap_metadata(struct super_block *sb,
1291 struct buffer_head *bh,
1292 struct reiserfs_bitmap_info *info)
1293{
1294 unsigned long *cur = (unsigned long *)(bh->b_data + bh->b_size);
1295
1296 info->first_zero_hint = 1 << (sb->s_blocksize_bits + 3);
1297
1298 while (--cur >= (unsigned long *)bh->b_data) {
1299 int base = ((char *)cur - bh->b_data) << 3;
1300
1301 /* 0 and ~0 are special, we can optimize for them */
1302 if (*cur == 0) {
1303 info->first_zero_hint = base;
1304 info->free_count += BITS_PER_LONG;
1305 } else if (*cur != ~0L) { /* A mix, investigate */
1306 int b;
1307 for (b = BITS_PER_LONG - 1; b >= 0; b--) {
1308 if (!reiserfs_test_le_bit(b, cur)) {
1309 info->first_zero_hint = base + b;
1310 info->free_count++;
1311 }
1312 }
1313 }
1314 }
1315 /* The first bit must ALWAYS be 1 */
1316 BUG_ON(info->first_zero_hint == 0);
1317}
1318
1319struct buffer_head *reiserfs_read_bitmap_block(struct super_block *sb,
1320 unsigned int bitmap)
1321{
1322 b_blocknr_t block = (sb->s_blocksize << 3) * bitmap;
1323 struct buffer_head *bh;
1324
1325 /* Way old format filesystems had the bitmaps packed up front.
1326 * I doubt there are any of these left, but just in case... */
1327 if (unlikely(test_bit(REISERFS_OLD_FORMAT,
1328 &(REISERFS_SB(sb)->s_properties))))
1329 block = REISERFS_SB(sb)->s_sbh->b_blocknr + 1 + bitmap;
1330 else if (bitmap == 0)
1331 block = (REISERFS_DISK_OFFSET_IN_BYTES >> sb->s_blocksize_bits) + 1;
1332
1333 bh = sb_getblk(sb, block);
1334 if (!buffer_uptodate(bh))
1335 ll_rw_block(READ, 1, &bh);
1336
1337 return bh;
1338}
1339
1340int reiserfs_init_bitmap_cache(struct super_block *sb)
1341{
1342 struct reiserfs_bitmap_info *bitmap;
1343 int i;
1344
1345 bitmap = vmalloc(sizeof (*bitmap) * SB_BMAP_NR(sb));
1346 if (bitmap == NULL)
1347 return -ENOMEM;
1348
1349 memset(bitmap, 0, sizeof (*bitmap) * SB_BMAP_NR(sb));
1350
1351 for (i = 0; i < SB_BMAP_NR(sb); i++)
1352 bitmap[i].bh = reiserfs_read_bitmap_block(sb, i);
1353
1354 /* make sure we have them all */
1355 for (i = 0; i < SB_BMAP_NR(sb); i++) {
1356 wait_on_buffer(bitmap[i].bh);
1357 if (!buffer_uptodate(bitmap[i].bh)) {
1358 reiserfs_warning(sb, "sh-2029: %s: "
1359 "bitmap block (#%lu) reading failed",
1360 __FUNCTION__, bitmap[i].bh->b_blocknr);
1361 for (i = 0; i < SB_BMAP_NR(sb); i++)
1362 brelse(bitmap[i].bh);
1363 vfree(bitmap);
1364 return -EIO;
1365 }
1366 }
1367
1368 /* Cache the info on the bitmaps before we get rolling */
1369 for (i = 0; i < SB_BMAP_NR(sb); i++)
1370 reiserfs_cache_bitmap_metadata(sb, bitmap[i].bh, &bitmap[i]);
1371
1372 SB_AP_BITMAP(sb) = bitmap;
1373
1374 return 0;
1375}
diff --git a/fs/reiserfs/resize.c b/fs/reiserfs/resize.c
index 958b75978994..90d39fd3096f 100644
--- a/fs/reiserfs/resize.c
+++ b/fs/reiserfs/resize.c
@@ -132,6 +132,7 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new)
132 get_bh(bh); 132 get_bh(bh);
133 memset(bh->b_data, 0, sb_blocksize(sb)); 133 memset(bh->b_data, 0, sb_blocksize(sb));
134 reiserfs_test_and_set_le_bit(0, bh->b_data); 134 reiserfs_test_and_set_le_bit(0, bh->b_data);
135 reiserfs_cache_bitmap_metadata(s, bh, bitmap + i);
135 136
136 set_buffer_uptodate(bh); 137 set_buffer_uptodate(bh);
137 mark_buffer_dirty(bh); 138 mark_buffer_dirty(bh);
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index db2c581df766..c78e99e196fa 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -1243,118 +1243,6 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
1243 return 0; 1243 return 0;
1244} 1244}
1245 1245
1246/* load_bitmap_info_data - Sets up the reiserfs_bitmap_info structure from disk.
1247 * @sb - superblock for this filesystem
1248 * @bi - the bitmap info to be loaded. Requires that bi->bh is valid.
1249 *
1250 * This routine counts how many free bits there are, finding the first zero
1251 * as a side effect. Could also be implemented as a loop of test_bit() calls, or
1252 * a loop of find_first_zero_bit() calls. This implementation is similar to
1253 * find_first_zero_bit(), but doesn't return after it finds the first bit.
1254 * Should only be called on fs mount, but should be fairly efficient anyways.
1255 *
1256 * bi->first_zero_hint is considered unset if it == 0, since the bitmap itself
1257 * will * invariably occupt block 0 represented in the bitmap. The only
1258 * exception to this is when free_count also == 0, since there will be no
1259 * free blocks at all.
1260 */
1261
1262static void load_bitmap_info_data(struct super_block *sb,
1263 struct reiserfs_bitmap_info *bi)
1264{
1265 unsigned long *cur = (unsigned long *)bi->bh->b_data;
1266
1267 while ((char *)cur < (bi->bh->b_data + sb->s_blocksize)) {
1268
1269 /* No need to scan if all 0's or all 1's.
1270 * Since we're only counting 0's, we can simply ignore all 1's */
1271 if (*cur == 0) {
1272 if (bi->first_zero_hint == 0) {
1273 bi->first_zero_hint =
1274 ((char *)cur - bi->bh->b_data) << 3;
1275 }
1276 bi->free_count += sizeof(unsigned long) * 8;
1277 } else if (*cur != ~0L) {
1278 int b;
1279 for (b = 0; b < sizeof(unsigned long) * 8; b++) {
1280 if (!reiserfs_test_le_bit(b, cur)) {
1281 bi->free_count++;
1282 if (bi->first_zero_hint == 0)
1283 bi->first_zero_hint =
1284 (((char *)cur -
1285 bi->bh->b_data) << 3) + b;
1286 }
1287 }
1288 }
1289 cur++;
1290 }
1291
1292#ifdef CONFIG_REISERFS_CHECK
1293// This outputs a lot of unneded info on big FSes
1294// reiserfs_warning ("bitmap loaded from block %d: %d free blocks",
1295// bi->bh->b_blocknr, bi->free_count);
1296#endif
1297}
1298
1299static int read_bitmaps(struct super_block *s)
1300{
1301 int i, bmap_nr;
1302
1303 SB_AP_BITMAP(s) =
1304 vmalloc(sizeof(struct reiserfs_bitmap_info) * SB_BMAP_NR(s));
1305 if (SB_AP_BITMAP(s) == 0)
1306 return 1;
1307 memset(SB_AP_BITMAP(s), 0,
1308 sizeof(struct reiserfs_bitmap_info) * SB_BMAP_NR(s));
1309 for (i = 0, bmap_nr =
1310 REISERFS_DISK_OFFSET_IN_BYTES / s->s_blocksize + 1;
1311 i < SB_BMAP_NR(s); i++, bmap_nr = s->s_blocksize * 8 * i) {
1312 SB_AP_BITMAP(s)[i].bh = sb_getblk(s, bmap_nr);
1313 if (!buffer_uptodate(SB_AP_BITMAP(s)[i].bh))
1314 ll_rw_block(READ, 1, &SB_AP_BITMAP(s)[i].bh);
1315 }
1316 for (i = 0; i < SB_BMAP_NR(s); i++) {
1317 wait_on_buffer(SB_AP_BITMAP(s)[i].bh);
1318 if (!buffer_uptodate(SB_AP_BITMAP(s)[i].bh)) {
1319 reiserfs_warning(s, "sh-2029: reiserfs read_bitmaps: "
1320 "bitmap block (#%lu) reading failed",
1321 SB_AP_BITMAP(s)[i].bh->b_blocknr);
1322 for (i = 0; i < SB_BMAP_NR(s); i++)
1323 brelse(SB_AP_BITMAP(s)[i].bh);
1324 vfree(SB_AP_BITMAP(s));
1325 SB_AP_BITMAP(s) = NULL;
1326 return 1;
1327 }
1328 load_bitmap_info_data(s, SB_AP_BITMAP(s) + i);
1329 }
1330 return 0;
1331}
1332
1333static int read_old_bitmaps(struct super_block *s)
1334{
1335 int i;
1336 struct reiserfs_super_block *rs = SB_DISK_SUPER_BLOCK(s);
1337 int bmp1 = (REISERFS_OLD_DISK_OFFSET_IN_BYTES / s->s_blocksize) + 1; /* first of bitmap blocks */
1338
1339 /* read true bitmap */
1340 SB_AP_BITMAP(s) =
1341 vmalloc(sizeof(struct reiserfs_buffer_info *) * sb_bmap_nr(rs));
1342 if (SB_AP_BITMAP(s) == 0)
1343 return 1;
1344
1345 memset(SB_AP_BITMAP(s), 0,
1346 sizeof(struct reiserfs_buffer_info *) * sb_bmap_nr(rs));
1347
1348 for (i = 0; i < sb_bmap_nr(rs); i++) {
1349 SB_AP_BITMAP(s)[i].bh = sb_bread(s, bmp1 + i);
1350 if (!SB_AP_BITMAP(s)[i].bh)
1351 return 1;
1352 load_bitmap_info_data(s, SB_AP_BITMAP(s) + i);
1353 }
1354
1355 return 0;
1356}
1357
1358static int read_super_block(struct super_block *s, int offset) 1246static int read_super_block(struct super_block *s, int offset)
1359{ 1247{
1360 struct buffer_head *bh; 1248 struct buffer_head *bh;
@@ -1736,7 +1624,7 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
1736 sbi->s_mount_state = SB_REISERFS_STATE(s); 1624 sbi->s_mount_state = SB_REISERFS_STATE(s);
1737 sbi->s_mount_state = REISERFS_VALID_FS; 1625 sbi->s_mount_state = REISERFS_VALID_FS;
1738 1626
1739 if (old_format ? read_old_bitmaps(s) : read_bitmaps(s)) { 1627 if ((errval = reiserfs_init_bitmap_cache(s))) {
1740 SWARN(silent, s, 1628 SWARN(silent, s,
1741 "jmacd-8: reiserfs_fill_super: unable to read bitmap"); 1629 "jmacd-8: reiserfs_fill_super: unable to read bitmap");
1742 goto error; 1630 goto error;
diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h
index 9c63abffd7b2..7bc6bfb86253 100644
--- a/include/linux/reiserfs_fs.h
+++ b/include/linux/reiserfs_fs.h
@@ -2073,6 +2073,10 @@ void reiserfs_init_alloc_options(struct super_block *s);
2073 */ 2073 */
2074__le32 reiserfs_choose_packing(struct inode *dir); 2074__le32 reiserfs_choose_packing(struct inode *dir);
2075 2075
2076int reiserfs_init_bitmap_cache(struct super_block *sb);
2077void reiserfs_free_bitmap_cache(struct super_block *sb);
2078void reiserfs_cache_bitmap_metadata(struct super_block *sb, struct buffer_head *bh, struct reiserfs_bitmap_info *info);
2079struct buffer_head *reiserfs_read_bitmap_block(struct super_block *sb, unsigned int bitmap);
2076int is_reusable(struct super_block *s, b_blocknr_t block, int bit_value); 2080int is_reusable(struct super_block *s, b_blocknr_t block, int bit_value);
2077void reiserfs_free_block(struct reiserfs_transaction_handle *th, struct inode *, 2081void reiserfs_free_block(struct reiserfs_transaction_handle *th, struct inode *,
2078 b_blocknr_t, int for_unformatted); 2082 b_blocknr_t, int for_unformatted);