Are you saying that you allow bitmaps to be unloaded? If yes, how about
making that a separate option, and not the default?
Hans
Jeff Mahoney wrote:
> This is the patch the three previous ones have been leading up to.
>
> It changes the behavior of ReiserFS from loading and caching all the bitmaps
> as special, to treating the bitmaps like any other bit of metadata and just
> letting the system-wide caches figure out what to hang on to.
>
> Buffer heads are allocated on the fly, so there is no need to retain pointers
> to all of them. The caching of the metadata occurs when the data is read
> and updated, and is considered invalid and uncached until then.
>
> fs/reiserfs/bitmap.c | 76
> ++++++++++++++++++++---------------------
> fs/reiserfs/resize.c | 24 +++++++++---
> fs/reiserfs/super.c | 25 -------------
> include/linux/reiserfs_fs_sb.h | 1
> 4 files changed, 56 insertions(+), 70 deletions(-)
>
>Signed-off-by: Jeff Mahoney <[EMAIL PROTECTED]>
>
>diff -ruNpX ../dontdiff linux-2.6.15.orig.staging1/fs/reiserfs/bitmap.c
>linux-2.6.15.orig.staging2/fs/reiserfs/bitmap.c
>--- linux-2.6.15.orig.staging1/fs/reiserfs/bitmap.c 2006-01-16
>16:53:33.626628760 -0500
>+++ linux-2.6.15.orig.staging2/fs/reiserfs/bitmap.c 2006-01-16
>16:53:33.634627544 -0500
>@@ -101,8 +101,9 @@ int is_reusable(struct super_block *s, b
> return 0;
> }
>
>- bh = SB_AP_BITMAP(s)[i].bh;
>- get_bh(bh);
>+ bh = reiserfs_read_bitmap_block(s, bmap);
>+ if (bh == NULL)
>+ return 0;
>
> if ((bit_value == 0 && reiserfs_test_le_bit(j, bh->b_data)) ||
> (bit_value == 1 && reiserfs_test_le_bit(j, bh->b_data) == 0)) {
>@@ -175,13 +176,10 @@ static int scan_bitmap_block(struct reis
> bmap_n);
> return 0;
> }
>- bh = bi->bh;
>- get_bh(bh);
>
>- if (buffer_locked(bi->bh)) {
>- PROC_INFO_INC(s, scan_bitmap.wait);
>- __wait_on_buffer(bh);
>- }
>+ bh = reiserfs_read_bitmap_block(s, bmap_n);
>+ if (bh == NULL)
>+ return 0;
>
> while (1) {
> if (bi->free_count < min) {
>@@ -286,9 +284,20 @@ static int bmap_hash_id(struct super_blo
> */
> static inline int block_group_used(struct super_block *s, u32 id)
> {
>- int bm;
>- bm = bmap_hash_id(s, id);
>- if (SB_AP_BITMAP(s)[bm].free_count > ((s->s_blocksize << 3) * 60 /
>100)) {
>+ int bm = bmap_hash_id(s, id);
>+ struct reiserfs_bitmap_info *info = &SB_AP_BITMAP(s)[bm];
>+
>+ /* If we don't have cached information on this bitmap block, we're
>+ * going to have to load it later anyway. Loading it here allows us
>+ * to make a better decision. This favors long-term performace gain
>+ * with a better on-disk layout vs. a short term gain of skipping the
>+ * read and potentially having a bad placement. */
>+ if (info->first_zero_hint == 0) {
>+ struct buffer_head *bh = reiserfs_read_bitmap_block(s, bm);
>+ brelse(bh);
>+ }
>+
>+ if (info->free_count > ((s->s_blocksize << 3) * 60 / 100)) {
> return 0;
> }
> return 1;
>@@ -414,8 +423,9 @@ static void _reiserfs_free_block(struct
> return;
> }
>
>- bmbh = apbi[nr].bh;
>- get_bh(bmbh);
>+ bmbh = reiserfs_read_bitmap_block(s, nr);
>+ if (!bmbh)
>+ return;
>
> reiserfs_prepare_for_journal(s, bmbh, 1);
>
>@@ -1319,6 +1329,7 @@ struct buffer_head *reiserfs_read_bitmap
> unsigned int bitmap)
> {
> unsigned int block = (sb->s_blocksize << 3) * bitmap;
>+ struct reiserfs_bitmap_info *info = SB_AP_BITMAP(sb) + bitmap;
> struct buffer_head *bh;
>
> /* Way old format filesystems had the bitmaps packed up front.
>@@ -1326,9 +1337,20 @@ struct buffer_head *reiserfs_read_bitmap
> if (test_bit(REISERFS_OLD_FORMAT, &(REISERFS_SB(sb)->s_properties)))
> block = REISERFS_SB(sb)->s_sbh->b_blocknr + 1 + bitmap;
>
>- bh = sb_getblk(sb, block);
>- if (!buffer_uptodate(bh))
>- ll_rw_block(READ, 1, &bh);
>+ bh = sb_bread(sb, block);
>+ if (bh == NULL)
>+ reiserfs_warning(sb, "sh-2029: reiserfs read_bitmaps: "
>+ "bitmap block (#%lu) reading failed",
>+ bh->b_blocknr);
>+ else {
>+ if (buffer_locked(bh)) {
>+ PROC_INFO_INC(s, scan_bitmap.wait);
>+ __wait_on_buffer(bh);
>+ }
>+
>+ if (info->first_zero_hint == 0)
>+ reiserfs_cache_bitmap_metadata(sb, bh, info);
>+ }
>
> return bh;
> }
>@@ -1336,7 +1358,6 @@ struct buffer_head *reiserfs_read_bitmap
> int reiserfs_init_bitmap_cache(struct super_block *sb)
> {
> struct reiserfs_bitmap_info *bitmap;
>- int i;
>
> bitmap = vmalloc(sizeof (*bitmap) * SB_BMAP_NR(sb));
> if (bitmap == NULL)
>@@ -1344,27 +1365,6 @@ int reiserfs_init_bitmap_cache(struct su
>
> memset(bitmap, 0, sizeof (*bitmap) * SB_BMAP_NR(sb));
>
>- for (i = 0; i < SB_BMAP_NR(sb); i++)
>- bitmap[i].bh = reiserfs_read_bitmap_block(sb, i);
>-
>- /* make sure we have them all */
>- for (i = 0; i < SB_BMAP_NR(sb); i++) {
>- wait_on_buffer(bitmap[i].bh);
>- if (!buffer_uptodate(bitmap[i].bh)) {
>- reiserfs_warning(sb, "sh-2029: reiserfs read_bitmaps: "
>- "bitmap block (#%lu) reading failed",
>- bitmap[i].bh->b_blocknr);
>- for (i = 0; i < SB_BMAP_NR(sb); i++)
>- brelse(bitmap[i].bh);
>- vfree(bitmap);
>- return 1;
>- }
>- }
>-
>- /* Cache the info on the bitmaps before we get rolling */
>- for (i = 0; i < SB_BMAP_NR(sb); i++)
>- reiserfs_cache_bitmap_metadata(sb, bitmap[i].bh, &bitmap[i]);
>-
> SB_AP_BITMAP(sb) = bitmap;
>
> return 0;
>diff -ruNpX ../dontdiff linux-2.6.15.orig.staging1/fs/reiserfs/resize.c
>linux-2.6.15.orig.staging2/fs/reiserfs/resize.c
>--- linux-2.6.15.orig.staging1/fs/reiserfs/resize.c 2006-01-16
>16:53:33.626628760 -0500
>+++ linux-2.6.15.orig.staging2/fs/reiserfs/resize.c 2006-01-16
>16:53:33.636627240 -0500
>@@ -128,8 +128,9 @@ int reiserfs_resize(struct super_block *
> * transaction begins, and the new bitmaps don't matter if the
> * transaction fails. */
> for (i = bmap_nr; i < bmap_nr_new; i++) {
>- bh = sb_getblk(s, i * s->s_blocksize * 8);
>- get_bh(bh);
>+ /* don't use read_bitmap_block since it will cache
>+ * the uninitialized bitmap */
>+ bh = sb_bread(s, i * s->s_blocksize * 8);
> memset(bh->b_data, 0, sb_blocksize(sb));
> reiserfs_test_and_set_le_bit(0, bh->b_data);
> reiserfs_cache_bitmap_metadata(s, bh, bitmap + i);
>@@ -140,7 +141,6 @@ int reiserfs_resize(struct super_block *
> // update bitmap_info stuff
> bitmap[i].first_zero_hint = 1;
> bitmap[i].free_count = sb_blocksize(sb) * 8 - 1;
>- bitmap[i].bh = bh;
> brelse(bh);
> }
> /* free old bitmap blocks array */
>@@ -157,8 +157,13 @@ int reiserfs_resize(struct super_block *
>
> /* Extend old last bitmap block - new blocks have been made available */
> info = SB_AP_BITMAP(s) + bmap_nr - 1;
>- bh = info->bh;
>- get_bh(bh);
>+ bh = reiserfs_read_bitmap_block(s, bmap_nr - 1);
>+ if (!bh) {
>+ int jerr = journal_end(&th, s, 10);
>+ if (jerr)
>+ return jerr;
>+ return -EIO;
>+ }
>
> reiserfs_prepare_for_journal(s, bh, 1);
> for (i = block_r; i < s->s_blocksize * 8; i++)
>@@ -172,8 +177,13 @@ int reiserfs_resize(struct super_block *
>
> /* Correct new last bitmap block - It may not be full */
> info = SB_AP_BITMAP(s) + bmap_nr_new - 1;
>- bh = info->bh;
>- get_bh(bh);
>+ bh = reiserfs_read_bitmap_block(s, bmap_nr_new - 1);
>+ if (!bh) {
>+ int jerr = journal_end(&th, s, 10);
>+ if (jerr)
>+ return jerr;
>+ return -EIO;
>+ }
>
> reiserfs_prepare_for_journal(s, bh, 1);
> for (i = block_r_new; i < s->s_blocksize * 8; i++)
>diff -ruNpX ../dontdiff linux-2.6.15.orig.staging1/fs/reiserfs/super.c
>linux-2.6.15.orig.staging2/fs/reiserfs/super.c
>--- linux-2.6.15.orig.staging1/fs/reiserfs/super.c 2006-01-16
>16:53:33.628628456 -0500
>+++ linux-2.6.15.orig.staging2/fs/reiserfs/super.c 2006-01-16
>16:53:33.637627088 -0500
>@@ -433,7 +433,6 @@ int remove_save_link(struct inode *inode
>
> static void reiserfs_put_super(struct super_block *s)
> {
>- int i;
> struct reiserfs_transaction_handle th;
> th.t_trans_id = 0;
>
>@@ -463,9 +462,6 @@ static void reiserfs_put_super(struct su
> */
> journal_release(&th, s);
>
>- for (i = 0; i < SB_BMAP_NR(s); i++)
>- brelse(SB_AP_BITMAP(s)[i].bh);
>-
> vfree(SB_AP_BITMAP(s));
>
> brelse(SB_BUFFER_WITH_SB(s));
>@@ -1365,7 +1361,6 @@ static int read_super_block(struct super
> /* after journal replay, reread all bitmap and super blocks */
> static int reread_meta_blocks(struct super_block *s)
> {
>- int i;
> ll_rw_block(READ, 1, &(SB_BUFFER_WITH_SB(s)));
> wait_on_buffer(SB_BUFFER_WITH_SB(s));
> if (!buffer_uptodate(SB_BUFFER_WITH_SB(s))) {
>@@ -1374,20 +1369,7 @@ static int reread_meta_blocks(struct sup
> return 1;
> }
>
>- for (i = 0; i < SB_BMAP_NR(s); i++) {
>- ll_rw_block(READ, 1, &(SB_AP_BITMAP(s)[i].bh));
>- wait_on_buffer(SB_AP_BITMAP(s)[i].bh);
>- if (!buffer_uptodate(SB_AP_BITMAP(s)[i].bh)) {
>- reiserfs_warning(s,
>- "reread_meta_blocks, error reading
>bitmap block number %d at %llu",
>- i,
>- (unsigned long long)SB_AP_BITMAP(s)[i].
>- bh->b_blocknr);
>- return 1;
>- }
>- }
> return 0;
>-
> }
>
> /////////////////////////////////////////////////////
>@@ -1814,13 +1796,8 @@ static int reiserfs_fill_super(struct su
> if (jinit_done) { /* kill the commit thread, free journal ram */
> journal_release_error(NULL, s);
> }
>- if (SB_DISK_SUPER_BLOCK(s)) {
>- for (j = 0; j < SB_BMAP_NR(s); j++) {
>- if (SB_AP_BITMAP(s))
>- brelse(SB_AP_BITMAP(s)[j].bh);
>- }
>+ if (SB_DISK_SUPER_BLOCK(s))
> vfree(SB_AP_BITMAP(s));
>- }
> if (SB_BUFFER_WITH_SB(s))
> brelse(SB_BUFFER_WITH_SB(s));
> #ifdef CONFIG_QUOTA
>diff -ruNpX ../dontdiff
>linux-2.6.15.orig.staging1/include/linux/reiserfs_fs_sb.h
>linux-2.6.15.orig.staging2/include/linux/reiserfs_fs_sb.h
>--- linux-2.6.15.orig.staging1/include/linux/reiserfs_fs_sb.h 2006-01-16
>16:53:29.453263208 -0500
>+++ linux-2.6.15.orig.staging2/include/linux/reiserfs_fs_sb.h 2006-01-16
>16:53:33.638626936 -0500
>@@ -267,7 +267,6 @@ struct reiserfs_bitmap_info {
> // FIXME: Won't work with block sizes > 8K
> __u16 first_zero_hint;
> __u16 free_count;
>- struct buffer_head *bh; /* the actual bitmap */
> };
>
> struct proc_dir_entry;
>
>
>
>