aboutsummaryrefslogtreecommitdiffstats
path: root/fs/reiserfs/bitmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/reiserfs/bitmap.c')
-rw-r--r--fs/reiserfs/bitmap.c88
1 files changed, 88 insertions, 0 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}