diff options
Diffstat (limited to 'fs/reiserfs/bitmap.c')
-rw-r--r-- | fs/reiserfs/bitmap.c | 88 |
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 | |||
1290 | void 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 | |||
1319 | struct 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 | |||
1340 | int 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 | } | ||