open 2.6.18-6: start adding first set of reiserfs backport

svn path=/dists/trunk/linux-2.6/; revision=7721
This commit is contained in:
maximilian attems 2006-11-08 23:14:08 +00:00
parent 250c85541c
commit 02bf1b0cf1
9 changed files with 1374 additions and 0 deletions

13
debian/changelog vendored
View File

@ -1,3 +1,16 @@
linux-2.6 (2.6.18-6) UNRELEASED; urgency=low
* reiserfs backport 2.6.19 SUSE fixes:
- use gcc -O1 in fs/reiserfs only for ancient gcc versions
- reiserfs_fsync should only use barriers when they are enabled
- Fix reiserfs latencies caused by data=ordered
- fix is_reusable bitmap check to not traverse the bitmap info array
- clean up bitmap block buffer head references
- reorganize bitmap loading functions
- on-demand bitmap loading
-- maximilian attems <maks@sternwelten.at> Thu, 9 Nov 2006 00:09:36 +0100
linux-2.6 (2.6.18-5) unstable; urgency=low
[ maximilian attems ]

View File

@ -0,0 +1,291 @@
From git-commits-head-owner@vger.kernel.org Wed Oct 4 17:36:49 2006
Date: Sun, 1 Oct 2006 08:01:29 GMT
Message-Id: <200610010801.k9181TNv010078@hera.kernel.org>
From: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
To: git-commits-head@vger.kernel.org
Subject: [PATCH] reiserfs: clean up bitmap block buffer head references
commit 0b3dc17bc0c0997bde9f5d7691ec0cae24258cf7
tree ecdbb6f830737358706b0ba7c628f47f9fdc0ff4
parent e1fabd3ccf02901374bffa434e0af472749a5bd9
author Jeff Mahoney <jeffm@suse.com> 1159684122 -0700
committer Linus Torvalds <torvalds@g5.osdl.org> 1159688367 -0700
[PATCH] reiserfs: clean up bitmap block buffer head references
Similar to the SB_JOURNAL cleanup that was accepted a while ago, this patch
uses a temporary variable for buffer head references from the bitmap info
array.
This makes the code much more readable in some areas.
It also uses proper reference counting, doing a get_bh() after using the
pointer from the array and brelse()'ing it later. This may seem silly, but a
later patch will replace the simple temporary variables with an actual read,
so the reference freeing will be used then.
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>
fs/reiserfs/bitmap.c | 60 ++++++++++++++++++++++++++++++---------------------
fs/reiserfs/resize.c | 60 +++++++++++++++++++++++++++++----------------------
2 files changed, 71 insertions(+), 49 deletions(-)
diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c
index 1022347..44d9410 100644
--- a/fs/reiserfs/bitmap.c
+++ b/fs/reiserfs/bitmap.c
@@ -59,6 +59,7 @@ #ifdef CONFIG_REISERFS_CHECK
int is_reusable(struct super_block *s, b_blocknr_t block, int bit_value)
{
int bmap, offset;
+ struct buffer_head *bh;
if (block == 0 || block >= SB_BLOCK_COUNT(s)) {
reiserfs_warning(s,
@@ -96,20 +97,21 @@ int is_reusable(struct super_block *s, b
return 0;
}
- if ((bit_value == 0 &&
- reiserfs_test_le_bit(offset, SB_AP_BITMAP(s)[bmap].bh->b_data)) ||
- (bit_value == 1 &&
- reiserfs_test_le_bit(offset, SB_AP_BITMAP(s)[bmap].bh->b_data) == 0)) {
+ bh = SB_AP_BITMAP(s)[bmap].bh;
+ get_bh(bh);
+
+ if ((bit_value == 0 && reiserfs_test_le_bit(offset, bh->b_data)) ||
+ (bit_value == 1 && reiserfs_test_le_bit(offset, bh->b_data) == 0)) {
reiserfs_warning(s,
"vs-4040: is_reusable: corresponding bit of block %lu does not "
"match required value (bmap==%d, offset==%d) test_bit==%d",
- block, bmap, offset, reiserfs_test_le_bit(offset,
- SB_AP_BITMAP
- (s)[bmap].bh->
- b_data));
+ block, bmap, offset,
+ reiserfs_test_le_bit(offset, bh->b_data));
+ brelse(bh);
return 0;
}
+ brelse(bh);
if (bit_value == 0 && block == SB_ROOT_BLOCK(s)) {
reiserfs_warning(s,
@@ -151,6 +153,7 @@ static int scan_bitmap_block(struct reis
{
struct super_block *s = th->t_super;
struct reiserfs_bitmap_info *bi = &SB_AP_BITMAP(s)[bmap_n];
+ struct buffer_head *bh;
int end, next;
int org = *beg;
@@ -169,22 +172,28 @@ static int scan_bitmap_block(struct reis
bmap_n);
return 0;
}
- if (buffer_locked(bi->bh)) {
+ bh = bi->bh;
+ get_bh(bh);
+
+ if (buffer_locked(bh)) {
PROC_INFO_INC(s, scan_bitmap.wait);
- __wait_on_buffer(bi->bh);
+ __wait_on_buffer(bh);
}
while (1) {
cont:
- if (bi->free_count < min)
+ if (bi->free_count < min) {
+ brelse(bh);
return 0; // No free blocks in this bitmap
+ }
/* search for a first zero bit -- beggining of a window */
*beg = reiserfs_find_next_zero_le_bit
- ((unsigned long *)(bi->bh->b_data), boundary, *beg);
+ ((unsigned long *)(bh->b_data), boundary, *beg);
if (*beg + min > boundary) { /* search for a zero bit fails or the rest of bitmap block
* cannot contain a zero window of minimum size */
+ brelse(bh);
return 0;
}
@@ -193,7 +202,7 @@ static int scan_bitmap_block(struct reis
/* first zero bit found; we check next bits */
for (end = *beg + 1;; end++) {
if (end >= *beg + max || end >= boundary
- || reiserfs_test_le_bit(end, bi->bh->b_data)) {
+ || reiserfs_test_le_bit(end, bh->b_data)) {
next = end;
break;
}
@@ -207,12 +216,12 @@ static int scan_bitmap_block(struct reis
* (end) points to one bit after the window end */
if (end - *beg >= min) { /* it seems we have found window of proper size */
int i;
- reiserfs_prepare_for_journal(s, bi->bh, 1);
+ reiserfs_prepare_for_journal(s, bh, 1);
/* try to set all blocks used checking are they still free */
for (i = *beg; i < end; i++) {
/* It seems that we should not check in journal again. */
if (reiserfs_test_and_set_le_bit
- (i, bi->bh->b_data)) {
+ (i, bh->b_data)) {
/* bit was set by another process
* while we slept in prepare_for_journal() */
PROC_INFO_INC(s, scan_bitmap.stolen);
@@ -224,17 +233,16 @@ static int scan_bitmap_block(struct reis
/* otherwise we clear all bit were set ... */
while (--i >= *beg)
reiserfs_test_and_clear_le_bit
- (i, bi->bh->b_data);
- reiserfs_restore_prepared_buffer(s,
- bi->
- bh);
+ (i, bh->b_data);
+ reiserfs_restore_prepared_buffer(s, bh);
*beg = org;
/* ... and search again in current block from beginning */
goto cont;
}
}
bi->free_count -= (end - *beg);
- journal_mark_dirty(th, s, bi->bh);
+ journal_mark_dirty(th, s, bh);
+ brelse(bh);
/* free block count calculation */
reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s),
@@ -383,7 +391,7 @@ static void _reiserfs_free_block(struct
{
struct super_block *s = th->t_super;
struct reiserfs_super_block *rs;
- struct buffer_head *sbh;
+ struct buffer_head *sbh, *bmbh;
struct reiserfs_bitmap_info *apbi;
int nr, offset;
@@ -404,16 +412,20 @@ static void _reiserfs_free_block(struct
return;
}
- reiserfs_prepare_for_journal(s, apbi[nr].bh, 1);
+ bmbh = apbi[nr].bh;
+ get_bh(bmbh);
+
+ reiserfs_prepare_for_journal(s, bmbh, 1);
/* clear bit for the given block in bit map */
- if (!reiserfs_test_and_clear_le_bit(offset, apbi[nr].bh->b_data)) {
+ if (!reiserfs_test_and_clear_le_bit(offset, bmbh->b_data)) {
reiserfs_warning(s, "vs-4080: reiserfs_free_block: "
"free_block (%s:%lu)[dev:blocknr]: bit already cleared",
reiserfs_bdevname(s), block);
}
apbi[nr].free_count++;
- journal_mark_dirty(th, s, apbi[nr].bh);
+ journal_mark_dirty(th, s, bmbh);
+ brelse(bmbh);
reiserfs_prepare_for_journal(s, sbh, 1);
/* update super block */
diff --git a/fs/reiserfs/resize.c b/fs/reiserfs/resize.c
index 39cc7f4..958b759 100644
--- a/fs/reiserfs/resize.c
+++ b/fs/reiserfs/resize.c
@@ -22,6 +22,7 @@ int reiserfs_resize(struct super_block *
int err = 0;
struct reiserfs_super_block *sb;
struct reiserfs_bitmap_info *bitmap;
+ struct reiserfs_bitmap_info *info;
struct reiserfs_bitmap_info *old_bitmap = SB_AP_BITMAP(s);
struct buffer_head *bh;
struct reiserfs_transaction_handle th;
@@ -127,16 +128,19 @@ 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++) {
- bitmap[i].bh = sb_getblk(s, i * s->s_blocksize * 8);
- memset(bitmap[i].bh->b_data, 0, sb_blocksize(sb));
- reiserfs_test_and_set_le_bit(0, bitmap[i].bh->b_data);
-
- set_buffer_uptodate(bitmap[i].bh);
- mark_buffer_dirty(bitmap[i].bh);
- sync_dirty_buffer(bitmap[i].bh);
+ bh = sb_getblk(s, i * s->s_blocksize * 8);
+ get_bh(bh);
+ memset(bh->b_data, 0, sb_blocksize(sb));
+ reiserfs_test_and_set_le_bit(0, bh->b_data);
+
+ set_buffer_uptodate(bh);
+ mark_buffer_dirty(bh);
+ sync_dirty_buffer(bh);
// 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 */
SB_AP_BITMAP(s) = bitmap;
@@ -150,30 +154,36 @@ int reiserfs_resize(struct super_block *
if (err)
return err;
- /* correct last bitmap blocks in old and new disk layout */
- reiserfs_prepare_for_journal(s, SB_AP_BITMAP(s)[bmap_nr - 1].bh, 1);
+ /* 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);
+
+ reiserfs_prepare_for_journal(s, bh, 1);
for (i = block_r; i < s->s_blocksize * 8; i++)
- reiserfs_test_and_clear_le_bit(i,
- SB_AP_BITMAP(s)[bmap_nr -
- 1].bh->b_data);
- SB_AP_BITMAP(s)[bmap_nr - 1].free_count += s->s_blocksize * 8 - block_r;
- if (!SB_AP_BITMAP(s)[bmap_nr - 1].first_zero_hint)
- SB_AP_BITMAP(s)[bmap_nr - 1].first_zero_hint = block_r;
+ reiserfs_test_and_clear_le_bit(i, bh->b_data);
+ info->free_count += s->s_blocksize * 8 - block_r;
+ if (!info->first_zero_hint)
+ info->first_zero_hint = block_r;
+
+ journal_mark_dirty(&th, s, bh);
+ brelse(bh);
- journal_mark_dirty(&th, s, SB_AP_BITMAP(s)[bmap_nr - 1].bh);
+ /* 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);
- reiserfs_prepare_for_journal(s, SB_AP_BITMAP(s)[bmap_nr_new - 1].bh, 1);
+ reiserfs_prepare_for_journal(s, bh, 1);
for (i = block_r_new; i < s->s_blocksize * 8; i++)
- reiserfs_test_and_set_le_bit(i,
- SB_AP_BITMAP(s)[bmap_nr_new -
- 1].bh->b_data);
- journal_mark_dirty(&th, s, SB_AP_BITMAP(s)[bmap_nr_new - 1].bh);
+ reiserfs_test_and_set_le_bit(i, bh->b_data);
+ journal_mark_dirty(&th, s, bh);
+ brelse(bh);
- SB_AP_BITMAP(s)[bmap_nr_new - 1].free_count -=
- s->s_blocksize * 8 - block_r_new;
+ info->free_count -= s->s_blocksize * 8 - block_r_new;
/* Extreme case where last bitmap is the only valid block in itself. */
- if (!SB_AP_BITMAP(s)[bmap_nr_new - 1].free_count)
- SB_AP_BITMAP(s)[bmap_nr_new - 1].first_zero_hint = 0;
+ if (!info->free_count)
+ info->first_zero_hint = 0;
/* update super */
reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1);
free_blocks = SB_FREE_BLOCKS(s);

View File

@ -0,0 +1,184 @@
From git-commits-head-owner@vger.kernel.org Wed Oct 4 17:36:47 2006
Return-Path: <git-commits-head-owner@vger.kernel.org>
Delivered-To: unknown
Received: from baikonur.stro.at (213.239.196.228) by nancy with IMAP4-SSL; 04
Oct 2006 15:36:47 -0000
X-Original-To: janitor@sternwelten.at
Delivered-To: janitor@sternwelten.at
Received: from vger.kernel.org (vger.kernel.org [209.132.176.167])
by baikonur.stro.at (Postfix) with ESMTP id 3DFD35C066
for <janitor@sternwelten.at>; Sun, 1 Oct 2006 10:01:38 +0200 (CEST)
Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
id S932105AbWJAIBp (ORCPT <rfc822;janitor@sternwelten.at>);
Sun, 1 Oct 2006 04:01:45 -0400
Received: (majordomo@vger.kernel.org) by vger.kernel.org id S932106AbWJAIBp
(ORCPT <rfc822;git-commits-head-outgoing>);
Sun, 1 Oct 2006 04:01:45 -0400
Received: from hera.kernel.org ([140.211.167.34]:36786 "EHLO hera.kernel.org")
by vger.kernel.org with ESMTP id S932105AbWJAIB3 (ORCPT
<rfc822;git-commits-head@vger.kernel.org>);
Sun, 1 Oct 2006 04:01:29 -0400
Received: from hera.kernel.org (IDENT:U2FsdGVkX1/qIwMDDPAqUjfbNz4+pldcJIqmPXsPjR0@localhost [127.0.0.1])
by hera.kernel.org (8.13.7/8.13.7) with ESMTP id k9181St4010065
(version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO)
for <git-commits-head@vger.kernel.org>; Sun, 1 Oct 2006 08:01:28 GMT
Received: (from dwmw2@localhost)
by hera.kernel.org (8.13.7/8.13.1/Submit) id k9181Rot010064
for git-commits-head@vger.kernel.org; Sun, 1 Oct 2006 08:01:27 GMT
Date: Sun, 1 Oct 2006 08:01:27 GMT
Message-Id: <200610010801.k9181Rot010064@hera.kernel.org>
From: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
To: git-commits-head@vger.kernel.org
Subject: [PATCH] reiserfs: fix is_reusable bitmap check to not traverse the bitmap info array
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
X-Git-Commit: e1fabd3ccf02901374bffa434e0af472749a5bd9
X-Git-Parent: 8ef386092d7c2891bd7acefb2a87f878f7e9a0d6
Sender: git-commits-head-owner@vger.kernel.org
Precedence: bulk
X-Mailing-List: git-commits-head@vger.kernel.org
X-Virus-Scanned: by Amavis (ClamAV) at stro.at
Status: RO
Content-Length: 5049
commit e1fabd3ccf02901374bffa434e0af472749a5bd9
tree 66d618e98020422874a521142ca2da797c9930f3
parent 8ef386092d7c2891bd7acefb2a87f878f7e9a0d6
author Jeff Mahoney <jeffm@suse.com> 1159684120 -0700
committer Linus Torvalds <torvalds@g5.osdl.org> 1159688367 -0700
[PATCH] reiserfs: fix is_reusable bitmap check to not traverse the bitmap info array
There is a check in is_reusable to determine if a particular block is a bitmap
block. It verifies this by going through the array of bitmap block buffer
heads and comparing the block number to each one.
Bitmap blocks are at defined locations on the disk in both old and current
formats. Simply checking against the known good values is enough.
This is a trivial optimization for a non-production codepath, but this is the
first in a series of patches that will ultimately remove the buffer heads from
that array.
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>
fs/reiserfs/bitmap.c | 40 +++++++++++++++++++++++++---------------
fs/reiserfs/super.c | 2 ++
include/linux/reiserfs_fs_sb.h | 1 +
3 files changed, 28 insertions(+), 15 deletions(-)
diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c
index 4a7dbde..1022347 100644
--- a/fs/reiserfs/bitmap.c
+++ b/fs/reiserfs/bitmap.c
@@ -50,16 +50,15 @@ static inline void get_bit_address(struc
{
/* It is in the bitmap block number equal to the block
* number divided by the number of bits in a block. */
- *bmap_nr = block / (s->s_blocksize << 3);
+ *bmap_nr = block >> (s->s_blocksize_bits + 3);
/* Within that bitmap block it is located at bit offset *offset. */
*offset = block & ((s->s_blocksize << 3) - 1);
- return;
}
#ifdef CONFIG_REISERFS_CHECK
int is_reusable(struct super_block *s, b_blocknr_t block, int bit_value)
{
- int i, j;
+ int bmap, offset;
if (block == 0 || block >= SB_BLOCK_COUNT(s)) {
reiserfs_warning(s,
@@ -68,34 +67,45 @@ int is_reusable(struct super_block *s, b
return 0;
}
- /* it can't be one of the bitmap blocks */
- for (i = 0; i < SB_BMAP_NR(s); i++)
- if (block == SB_AP_BITMAP(s)[i].bh->b_blocknr) {
+ get_bit_address(s, block, &bmap, &offset);
+
+ /* Old format filesystem? Unlikely, but the bitmaps are all up front so
+ * we need to account for it. */
+ if (unlikely(test_bit(REISERFS_OLD_FORMAT,
+ &(REISERFS_SB(s)->s_properties)))) {
+ b_blocknr_t bmap1 = REISERFS_SB(s)->s_sbh->b_blocknr + 1;
+ if (block >= bmap1 && block <= bmap1 + SB_BMAP_NR(s)) {
+ reiserfs_warning(s, "vs: 4019: is_reusable: "
+ "bitmap block %lu(%u) can't be freed or reused",
+ block, SB_BMAP_NR(s));
+ return 0;
+ }
+ } else {
+ if (offset == 0) {
reiserfs_warning(s, "vs: 4020: is_reusable: "
"bitmap block %lu(%u) can't be freed or reused",
block, SB_BMAP_NR(s));
return 0;
}
+ }
- get_bit_address(s, block, &i, &j);
-
- if (i >= SB_BMAP_NR(s)) {
+ if (bmap >= SB_BMAP_NR(s)) {
reiserfs_warning(s,
"vs-4030: is_reusable: there is no so many bitmap blocks: "
- "block=%lu, bitmap_nr=%d", block, i);
+ "block=%lu, bitmap_nr=%d", block, bmap);
return 0;
}
if ((bit_value == 0 &&
- reiserfs_test_le_bit(j, SB_AP_BITMAP(s)[i].bh->b_data)) ||
+ reiserfs_test_le_bit(offset, SB_AP_BITMAP(s)[bmap].bh->b_data)) ||
(bit_value == 1 &&
- reiserfs_test_le_bit(j, SB_AP_BITMAP(s)[i].bh->b_data) == 0)) {
+ reiserfs_test_le_bit(offset, SB_AP_BITMAP(s)[bmap].bh->b_data) == 0)) {
reiserfs_warning(s,
"vs-4040: is_reusable: corresponding bit of block %lu does not "
- "match required value (i==%d, j==%d) test_bit==%d",
- block, i, j, reiserfs_test_le_bit(j,
+ "match required value (bmap==%d, offset==%d) test_bit==%d",
+ block, bmap, offset, reiserfs_test_le_bit(offset,
SB_AP_BITMAP
- (s)[i].bh->
+ (s)[bmap].bh->
b_data));
return 0;
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index 80fc3b3..db2c581 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -1818,6 +1818,8 @@ #endif
if (is_reiserfs_3_5(rs)
|| (is_reiserfs_jr(rs) && SB_VERSION(s) == REISERFS_VERSION_1))
set_bit(REISERFS_3_5, &(sbi->s_properties));
+ else if (old_format)
+ set_bit(REISERFS_OLD_FORMAT, &(sbi->s_properties));
else
set_bit(REISERFS_3_6, &(sbi->s_properties));
diff --git a/include/linux/reiserfs_fs_sb.h b/include/linux/reiserfs_fs_sb.h
index 31b4c0b..4f21ad3 100644
--- a/include/linux/reiserfs_fs_sb.h
+++ b/include/linux/reiserfs_fs_sb.h
@@ -414,6 +414,7 @@ #endif
/* Definitions of reiserfs on-disk properties: */
#define REISERFS_3_5 0
#define REISERFS_3_6 1
+#define REISERFS_OLD_FORMAT 2
enum reiserfs_mount_options {
/* Mount options */
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

View File

@ -0,0 +1,368 @@
From git-commits-head-owner@vger.kernel.org Wed Oct 4 17:36:49 2006
Date: Sun, 1 Oct 2006 08:01:31 GMT
Message-Id: <200610010801.k9181V7G010116@hera.kernel.org>
From: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
To: git-commits-head@vger.kernel.org
Subject: [PATCH] reiserfs: on-demand bitmap loading
commit 5065227b46235ec0131b383cc2f537069b55c6b6
tree 12187734ef619626c901b9d2b43ad72286d4d258
parent 6f01046b35d940079822827498a7dd6d3eec8c6b
author Jeff Mahoney <jeffm@suse.com> 1159684124 -0700
committer Linus Torvalds <torvalds@g5.osdl.org> 1159688368 -0700
[PATCH] reiserfs: on-demand bitmap loading
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.
I needed to remove the vs-4040 check for performing a duplicate operation on a
particular bit. The reason is that while the other sites for working with
bitmaps are allowed to schedule, is_reusable() is called from do_balance(),
which will panic if a schedule occurs in certain places.
The benefit of on-demand bitmaps clearly outweighs a sanity check that depends
on a compile-time option that is discouraged.
[akpm@osdl.org: warning fix]
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>
fs/reiserfs/bitmap.c | 97 ++++++++++++++++++-----------------------
fs/reiserfs/resize.c | 24 +++++++---
fs/reiserfs/super.c | 39 +++-------------
include/linux/reiserfs_fs_sb.h | 1
4 files changed, 70 insertions(+), 91 deletions(-)
diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c
index abdd6d9..cca1dbf 100644
--- a/fs/reiserfs/bitmap.c
+++ b/fs/reiserfs/bitmap.c
@@ -60,7 +60,6 @@ #ifdef CONFIG_REISERFS_CHECK
int is_reusable(struct super_block *s, b_blocknr_t block, int bit_value)
{
int bmap, offset;
- struct buffer_head *bh;
if (block == 0 || block >= SB_BLOCK_COUNT(s)) {
reiserfs_warning(s,
@@ -98,22 +97,6 @@ int is_reusable(struct super_block *s, b
return 0;
}
- bh = SB_AP_BITMAP(s)[bmap].bh;
- get_bh(bh);
-
- if ((bit_value == 0 && reiserfs_test_le_bit(offset, bh->b_data)) ||
- (bit_value == 1 && reiserfs_test_le_bit(offset, bh->b_data) == 0)) {
- reiserfs_warning(s,
- "vs-4040: is_reusable: corresponding bit of block %lu does not "
- "match required value (bmap==%d, offset==%d) test_bit==%d",
- block, bmap, offset,
- reiserfs_test_le_bit(offset, bh->b_data));
-
- brelse(bh);
- return 0;
- }
- brelse(bh);
-
if (bit_value == 0 && block == SB_ROOT_BLOCK(s)) {
reiserfs_warning(s,
"vs-4050: is_reusable: this is root block (%u), "
@@ -173,13 +156,10 @@ static int scan_bitmap_block(struct reis
bmap_n);
return 0;
}
- bh = bi->bh;
- get_bh(bh);
- if (buffer_locked(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) {
cont:
@@ -285,9 +265,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;
@@ -413,8 +404,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);
@@ -1320,6 +1312,7 @@ struct buffer_head *reiserfs_read_bitmap
unsigned int bitmap)
{
b_blocknr_t 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.
@@ -1330,9 +1323,21 @@ struct buffer_head *reiserfs_read_bitmap
else if (bitmap == 0)
block = (REISERFS_DISK_OFFSET_IN_BYTES >> sb->s_blocksize_bits) + 1;
- 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: %s: bitmap block (#%lu) "
+ "reading failed", __FUNCTION__, bh->b_blocknr);
+ else {
+ if (buffer_locked(bh)) {
+ PROC_INFO_INC(sb, scan_bitmap.wait);
+ __wait_on_buffer(bh);
+ }
+ BUG_ON(!buffer_uptodate(bh));
+ BUG_ON(atomic_read(&bh->b_count) == 0);
+
+ if (info->first_zero_hint == 0)
+ reiserfs_cache_bitmap_metadata(sb, bh, info);
+ }
return bh;
}
@@ -1340,7 +1345,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)
@@ -1348,28 +1352,15 @@ 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: %s: "
- "bitmap block (#%lu) reading failed",
- __FUNCTION__, bitmap[i].bh->b_blocknr);
- for (i = 0; i < SB_BMAP_NR(sb); i++)
- brelse(bitmap[i].bh);
- vfree(bitmap);
- return -EIO;
- }
- }
-
- /* 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;
}
+
+void reiserfs_free_bitmap_cache(struct super_block *sb)
+{
+ if (SB_AP_BITMAP(sb)) {
+ vfree(SB_AP_BITMAP(sb));
+ SB_AP_BITMAP(sb) = NULL;
+ }
+}
diff --git a/fs/reiserfs/resize.c b/fs/reiserfs/resize.c
index 90d39fd..3156847 100644
--- a/fs/reiserfs/resize.c
+++ b/fs/reiserfs/resize.c
@@ -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 --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index c78e99e..c89aa23 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -432,7 +432,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;
@@ -462,10 +461,7 @@ 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));
+ reiserfs_free_bitmap_cache(s);
brelse(SB_BUFFER_WITH_SB(s));
@@ -1344,7 +1340,6 @@ #endif
/* 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))) {
@@ -1353,20 +1348,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;
-
}
/////////////////////////////////////////////////////
@@ -1547,7 +1529,6 @@ #define SWARN(silent, s, ...) \
static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
{
struct inode *root_inode;
- int j;
struct reiserfs_transaction_handle th;
int old_format = 0;
unsigned long blocks;
@@ -1793,19 +1774,17 @@ #endif
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);
- }
- vfree(SB_AP_BITMAP(s));
- }
+
+ reiserfs_free_bitmap_cache(s);
if (SB_BUFFER_WITH_SB(s))
brelse(SB_BUFFER_WITH_SB(s));
#ifdef CONFIG_QUOTA
- for (j = 0; j < MAXQUOTAS; j++) {
- kfree(sbi->s_qf_names[j]);
- sbi->s_qf_names[j] = NULL;
+ {
+ int j;
+ for (j = 0; j < MAXQUOTAS; j++) {
+ kfree(sbi->s_qf_names[j]);
+ sbi->s_qf_names[j] = NULL;
+ }
}
#endif
kfree(sbi);
diff --git a/include/linux/reiserfs_fs_sb.h b/include/linux/reiserfs_fs_sb.h
index 4f21ad3..73e0bec 100644
--- a/include/linux/reiserfs_fs_sb.h
+++ b/include/linux/reiserfs_fs_sb.h
@@ -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;

View File

@ -0,0 +1,314 @@
From git-commits-head-owner@vger.kernel.org Wed Oct 4 17:36:48 2006
Date: Sun, 1 Oct 2006 08:01:30 GMT
Message-Id: <200610010801.k9181U4g010098@hera.kernel.org>
From: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
To: git-commits-head@vger.kernel.org
Subject: [PATCH] reiserfs: reorganize bitmap loading functions
commit 6f01046b35d940079822827498a7dd6d3eec8c6b
tree e65426389691c9d3e7d4f29da73725d15ee8e2f6
parent 0b3dc17bc0c0997bde9f5d7691ec0cae24258cf7
author Jeff Mahoney <jeffm@suse.com> 1159684123 -0700
committer Linus Torvalds <torvalds@g5.osdl.org> 1159688367 -0700
[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>
fs/reiserfs/bitmap.c | 88 +++++++++++++++++++++++++++++++++
fs/reiserfs/resize.c | 1
fs/reiserfs/super.c | 114 --------------------------------------------
include/linux/reiserfs_fs.h | 4 +
4 files changed, 94 insertions(+), 113 deletions(-)
diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c
index 44d9410..abdd6d9 100644
--- a/fs/reiserfs/bitmap.c
+++ b/fs/reiserfs/bitmap.c
@@ -9,6 +9,7 @@ #include <linux/errno.h>
#include <linux/buffer_head.h>
#include <linux/kernel.h>
#include <linux/pagemap.h>
+#include <linux/vmalloc.h>
#include <linux/reiserfs_fs_sb.h>
#include <linux/reiserfs_fs_i.h>
#include <linux/quotaops.h>
@@ -1285,3 +1286,90 @@ int reiserfs_can_fit_pages(struct super_
return space > 0 ? space : 0;
}
+
+void reiserfs_cache_bitmap_metadata(struct super_block *sb,
+ struct buffer_head *bh,
+ struct reiserfs_bitmap_info *info)
+{
+ unsigned long *cur = (unsigned long *)(bh->b_data + bh->b_size);
+
+ info->first_zero_hint = 1 << (sb->s_blocksize_bits + 3);
+
+ while (--cur >= (unsigned long *)bh->b_data) {
+ int base = ((char *)cur - bh->b_data) << 3;
+
+ /* 0 and ~0 are special, we can optimize for them */
+ if (*cur == 0) {
+ info->first_zero_hint = base;
+ info->free_count += BITS_PER_LONG;
+ } else if (*cur != ~0L) { /* A mix, investigate */
+ int b;
+ for (b = BITS_PER_LONG - 1; b >= 0; b--) {
+ if (!reiserfs_test_le_bit(b, cur)) {
+ info->first_zero_hint = base + b;
+ info->free_count++;
+ }
+ }
+ }
+ }
+ /* The first bit must ALWAYS be 1 */
+ BUG_ON(info->first_zero_hint == 0);
+}
+
+struct buffer_head *reiserfs_read_bitmap_block(struct super_block *sb,
+ unsigned int bitmap)
+{
+ b_blocknr_t block = (sb->s_blocksize << 3) * bitmap;
+ struct buffer_head *bh;
+
+ /* Way old format filesystems had the bitmaps packed up front.
+ * I doubt there are any of these left, but just in case... */
+ if (unlikely(test_bit(REISERFS_OLD_FORMAT,
+ &(REISERFS_SB(sb)->s_properties))))
+ block = REISERFS_SB(sb)->s_sbh->b_blocknr + 1 + bitmap;
+ else if (bitmap == 0)
+ block = (REISERFS_DISK_OFFSET_IN_BYTES >> sb->s_blocksize_bits) + 1;
+
+ bh = sb_getblk(sb, block);
+ if (!buffer_uptodate(bh))
+ ll_rw_block(READ, 1, &bh);
+
+ return bh;
+}
+
+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)
+ return -ENOMEM;
+
+ 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: %s: "
+ "bitmap block (#%lu) reading failed",
+ __FUNCTION__, bitmap[i].bh->b_blocknr);
+ for (i = 0; i < SB_BMAP_NR(sb); i++)
+ brelse(bitmap[i].bh);
+ vfree(bitmap);
+ return -EIO;
+ }
+ }
+
+ /* 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 --git a/fs/reiserfs/resize.c b/fs/reiserfs/resize.c
index 958b759..90d39fd 100644
--- a/fs/reiserfs/resize.c
+++ b/fs/reiserfs/resize.c
@@ -132,6 +132,7 @@ int reiserfs_resize(struct super_block *
get_bh(bh);
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);
set_buffer_uptodate(bh);
mark_buffer_dirty(bh);
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index db2c581..c78e99e 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -1243,118 +1243,6 @@ #endif
return 0;
}
-/* load_bitmap_info_data - Sets up the reiserfs_bitmap_info structure from disk.
- * @sb - superblock for this filesystem
- * @bi - the bitmap info to be loaded. Requires that bi->bh is valid.
- *
- * This routine counts how many free bits there are, finding the first zero
- * as a side effect. Could also be implemented as a loop of test_bit() calls, or
- * a loop of find_first_zero_bit() calls. This implementation is similar to
- * find_first_zero_bit(), but doesn't return after it finds the first bit.
- * Should only be called on fs mount, but should be fairly efficient anyways.
- *
- * bi->first_zero_hint is considered unset if it == 0, since the bitmap itself
- * will * invariably occupt block 0 represented in the bitmap. The only
- * exception to this is when free_count also == 0, since there will be no
- * free blocks at all.
- */
-
-static void load_bitmap_info_data(struct super_block *sb,
- struct reiserfs_bitmap_info *bi)
-{
- unsigned long *cur = (unsigned long *)bi->bh->b_data;
-
- while ((char *)cur < (bi->bh->b_data + sb->s_blocksize)) {
-
- /* No need to scan if all 0's or all 1's.
- * Since we're only counting 0's, we can simply ignore all 1's */
- if (*cur == 0) {
- if (bi->first_zero_hint == 0) {
- bi->first_zero_hint =
- ((char *)cur - bi->bh->b_data) << 3;
- }
- bi->free_count += sizeof(unsigned long) * 8;
- } else if (*cur != ~0L) {
- int b;
- for (b = 0; b < sizeof(unsigned long) * 8; b++) {
- if (!reiserfs_test_le_bit(b, cur)) {
- bi->free_count++;
- if (bi->first_zero_hint == 0)
- bi->first_zero_hint =
- (((char *)cur -
- bi->bh->b_data) << 3) + b;
- }
- }
- }
- cur++;
- }
-
-#ifdef CONFIG_REISERFS_CHECK
-// This outputs a lot of unneded info on big FSes
-// reiserfs_warning ("bitmap loaded from block %d: %d free blocks",
-// bi->bh->b_blocknr, bi->free_count);
-#endif
-}
-
-static int read_bitmaps(struct super_block *s)
-{
- int i, bmap_nr;
-
- SB_AP_BITMAP(s) =
- vmalloc(sizeof(struct reiserfs_bitmap_info) * SB_BMAP_NR(s));
- if (SB_AP_BITMAP(s) == 0)
- return 1;
- memset(SB_AP_BITMAP(s), 0,
- sizeof(struct reiserfs_bitmap_info) * SB_BMAP_NR(s));
- for (i = 0, bmap_nr =
- REISERFS_DISK_OFFSET_IN_BYTES / s->s_blocksize + 1;
- i < SB_BMAP_NR(s); i++, bmap_nr = s->s_blocksize * 8 * i) {
- SB_AP_BITMAP(s)[i].bh = sb_getblk(s, bmap_nr);
- if (!buffer_uptodate(SB_AP_BITMAP(s)[i].bh))
- ll_rw_block(READ, 1, &SB_AP_BITMAP(s)[i].bh);
- }
- for (i = 0; i < SB_BMAP_NR(s); i++) {
- wait_on_buffer(SB_AP_BITMAP(s)[i].bh);
- if (!buffer_uptodate(SB_AP_BITMAP(s)[i].bh)) {
- reiserfs_warning(s, "sh-2029: reiserfs read_bitmaps: "
- "bitmap block (#%lu) reading failed",
- SB_AP_BITMAP(s)[i].bh->b_blocknr);
- for (i = 0; i < SB_BMAP_NR(s); i++)
- brelse(SB_AP_BITMAP(s)[i].bh);
- vfree(SB_AP_BITMAP(s));
- SB_AP_BITMAP(s) = NULL;
- return 1;
- }
- load_bitmap_info_data(s, SB_AP_BITMAP(s) + i);
- }
- return 0;
-}
-
-static int read_old_bitmaps(struct super_block *s)
-{
- int i;
- struct reiserfs_super_block *rs = SB_DISK_SUPER_BLOCK(s);
- int bmp1 = (REISERFS_OLD_DISK_OFFSET_IN_BYTES / s->s_blocksize) + 1; /* first of bitmap blocks */
-
- /* read true bitmap */
- SB_AP_BITMAP(s) =
- vmalloc(sizeof(struct reiserfs_buffer_info *) * sb_bmap_nr(rs));
- if (SB_AP_BITMAP(s) == 0)
- return 1;
-
- memset(SB_AP_BITMAP(s), 0,
- sizeof(struct reiserfs_buffer_info *) * sb_bmap_nr(rs));
-
- for (i = 0; i < sb_bmap_nr(rs); i++) {
- SB_AP_BITMAP(s)[i].bh = sb_bread(s, bmp1 + i);
- if (!SB_AP_BITMAP(s)[i].bh)
- return 1;
- load_bitmap_info_data(s, SB_AP_BITMAP(s) + i);
- }
-
- return 0;
-}
-
static int read_super_block(struct super_block *s, int offset)
{
struct buffer_head *bh;
@@ -1736,7 +1624,7 @@ static int reiserfs_fill_super(struct su
sbi->s_mount_state = SB_REISERFS_STATE(s);
sbi->s_mount_state = REISERFS_VALID_FS;
- if (old_format ? read_old_bitmaps(s) : read_bitmaps(s)) {
+ if ((errval = reiserfs_init_bitmap_cache(s))) {
SWARN(silent, s,
"jmacd-8: reiserfs_fill_super: unable to read bitmap");
goto error;
diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h
index 9c63abf..7bc6bfb 100644
--- a/include/linux/reiserfs_fs.h
+++ b/include/linux/reiserfs_fs.h
@@ -2073,6 +2073,10 @@ void reiserfs_init_alloc_options(struct
*/
__le32 reiserfs_choose_packing(struct inode *dir);
+int reiserfs_init_bitmap_cache(struct super_block *sb);
+void reiserfs_free_bitmap_cache(struct super_block *sb);
+void reiserfs_cache_bitmap_metadata(struct super_block *sb, struct buffer_head *bh, struct reiserfs_bitmap_info *info);
+struct buffer_head *reiserfs_read_bitmap_block(struct super_block *sb, unsigned int bitmap);
int is_reusable(struct super_block *s, b_blocknr_t block, int bit_value);
void reiserfs_free_block(struct reiserfs_transaction_handle *th, struct inode *,
b_blocknr_t, int for_unformatted);

View File

@ -0,0 +1,38 @@
From git-commits-head-owner@vger.kernel.org Sat Sep 30 01:10:37 2006
Date: Fri, 29 Sep 2006 17:02:12 GMT
Message-Id: <200609291702.k8TH2C5A031438@hera.kernel.org>
From: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
To: git-commits-head@vger.kernel.org
Subject: [PATCH] reiserfs_fsync should only use barriers when they are enabled
commit 25736b1c692d436508585d1d710912e6f76be2d8
tree 8cf9a65b5a6d464ceabfe992b49a028a9a939198
parent d4328b40af16bae62ff8f854060d33daad237093
author Chris Mason <mason@suse.com> 1159520394 -0700
committer Linus Torvalds <torvalds@g5.osdl.org> 1159546691 -0700
[PATCH] reiserfs_fsync should only use barriers when they are enabled
make sure that reiserfs_fsync only triggers barriers when mounted with -o
barrier=flush
Signed-off-by: Chris Mason <mason@suse.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
fs/reiserfs/file.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index 1627edd..1cfbe85 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -130,7 +130,7 @@ static int reiserfs_sync_file(struct fil
reiserfs_write_lock(p_s_inode->i_sb);
barrier_done = reiserfs_commit_for_inode(p_s_inode);
reiserfs_write_unlock(p_s_inode->i_sb);
- if (barrier_done != 1)
+ if (barrier_done != 1 && reiserfs_barrier_flush(p_s_inode->i_sb))
blkdev_issue_flush(p_s_inode->i_sb->s_bdev, NULL);
if (barrier_done < 0)
return barrier_done;

View File

@ -0,0 +1,40 @@
From git-commits-head-owner@vger.kernel.org Sat Sep 30 01:10:28 2006
Date: Fri, 29 Sep 2006 17:01:39 GMT
Message-Id: <200609291701.k8TH1dVv030631@hera.kernel.org>
From: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
To: git-commits-head@vger.kernel.org
Subject: [PATCH] use gcc -O1 in fs/reiserfs only for ancient gcc versions
commit 42012cc4a2183c555a907eee32d7ce4fc7dc3a6a
tree 90fbd712085050fac8f06544e3186736539cf2bc
parent 4d24607bfaab3d02fd0d6e0ffc22f29c2bc8eb30
author Olaf Hering <olh@suse.de> 1159520361 -0700
committer Linus Torvalds <torvalds@g5.osdl.org> 1159546687 -0700
[PATCH] use gcc -O1 in fs/reiserfs only for ancient gcc versions
Only compile with -O1 if the (very old) compiler is broken. We use
reiserfs alot since SLES9 on ppc64, and it was never seen with gcc33.
Assume the broken gcc is gcc-3.4 or older.
Signed-off-by: Olaf Hering <olh@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
fs/reiserfs/Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/reiserfs/Makefile b/fs/reiserfs/Makefile
index 3a59309..0eb7ac0 100644
--- a/fs/reiserfs/Makefile
+++ b/fs/reiserfs/Makefile
@@ -28,7 +28,7 @@ # and causing a panic. Since this behavi
# will work around it. If any other architecture displays this behavior,
# add it here.
ifeq ($(CONFIG_PPC32),y)
-EXTRA_CFLAGS := -O1
+EXTRA_CFLAGS := $(call cc-ifversion, -lt, 0400, -O1)
endif
TAGS:

View File

@ -0,0 +1,119 @@
From git-commits-head-owner@vger.kernel.org Sat Sep 30 01:10:36 2006
Date: Fri, 29 Sep 2006 17:02:13 GMT
Message-Id: <200609291702.k8TH2D50031449@hera.kernel.org>
From: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
To: git-commits-head@vger.kernel.org
Subject: [PATCH] Fix reiserfs latencies caused by data=ordered
commit a3172027148120b8f8797cbecc7d0a0b215736a1
tree 9da7b5eafe136c8c5b9e76e9a9cccd70899df252
parent 25736b1c692d436508585d1d710912e6f76be2d8
author Chris Mason <mason@suse.com> 1159520396 -0700
committer Linus Torvalds <torvalds@g5.osdl.org> 1159546691 -0700
[PATCH] Fix reiserfs latencies caused by data=ordered
ReiserFS does periodic cleanup of old transactions in order to limit the
length of time a journal replay may take after a crash. Sometimes, writing
metadata from an old (already committed) transaction may require committing
a newer transaction, which also requires writing all data=ordered buffers.
This can cause very long stalls on journal_begin.
This patch makes sure new transactions will not need to be committed before
trying a periodic reclaim of an old transaction. It is low risk because if
a bad decision is made, it just means a slightly longer journal replay
after a crash.
Signed-off-by: Chris Mason <mason@suse.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
fs/reiserfs/journal.c | 54 +++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 43 insertions(+), 11 deletions(-)
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
index 9b3672d..e6b5ccf 100644
--- a/fs/reiserfs/journal.c
+++ b/fs/reiserfs/journal.c
@@ -1186,6 +1186,21 @@ static struct reiserfs_journal_list *fin
return NULL;
}
+static int newer_jl_done(struct reiserfs_journal_cnode *cn)
+{
+ struct super_block *sb = cn->sb;
+ b_blocknr_t blocknr = cn->blocknr;
+
+ cn = cn->hprev;
+ while (cn) {
+ if (cn->sb == sb && cn->blocknr == blocknr && cn->jlist &&
+ atomic_read(&cn->jlist->j_commit_left) != 0)
+ return 0;
+ cn = cn->hprev;
+ }
+ return 1;
+}
+
static void remove_journal_hash(struct super_block *,
struct reiserfs_journal_cnode **,
struct reiserfs_journal_list *, unsigned long,
@@ -1604,6 +1619,31 @@ #endif
return err;
}
+static int test_transaction(struct super_block *s,
+ struct reiserfs_journal_list *jl)
+{
+ struct reiserfs_journal_cnode *cn;
+
+ if (jl->j_len == 0 || atomic_read(&jl->j_nonzerolen) == 0)
+ return 1;
+
+ cn = jl->j_realblock;
+ while (cn) {
+ /* if the blocknr == 0, this has been cleared from the hash,
+ ** skip it
+ */
+ if (cn->blocknr == 0) {
+ goto next;
+ }
+ if (cn->bh && !newer_jl_done(cn))
+ return 0;
+ next:
+ cn = cn->next;
+ cond_resched();
+ }
+ return 0;
+}
+
static int write_one_transaction(struct super_block *s,
struct reiserfs_journal_list *jl,
struct buffer_chunk *chunk)
@@ -3433,16 +3473,6 @@ static void flush_async_commits(void *p)
flush_commit_list(p_s_sb, jl, 1);
}
unlock_kernel();
- /*
- * this is a little racey, but there's no harm in missing
- * the filemap_fdata_write
- */
- if (!atomic_read(&journal->j_async_throttle)
- && !reiserfs_is_journal_aborted(journal)) {
- atomic_inc(&journal->j_async_throttle);
- filemap_fdatawrite(p_s_sb->s_bdev->bd_inode->i_mapping);
- atomic_dec(&journal->j_async_throttle);
- }
}
/*
@@ -3844,7 +3874,9 @@ static void flush_old_journal_lists(stru
entry = journal->j_journal_list.next;
jl = JOURNAL_LIST_ENTRY(entry);
/* this check should always be run, to send old lists to disk */
- if (jl->j_timestamp < (now - (JOURNAL_MAX_TRANS_AGE * 4))) {
+ if (jl->j_timestamp < (now - (JOURNAL_MAX_TRANS_AGE * 4)) &&
+ atomic_read(&jl->j_commit_left) == 0 &&
+ test_transaction(s, jl)) {
flush_used_journal_lists(s, jl);
} else {
break;

7
debian/patches/series/6 vendored Normal file
View File

@ -0,0 +1,7 @@
+ features/fs-reiserfs-gcc-flags.patch
+ features/fs-reiserfs-fsync-barriers.patch
+ features/fs-reiserfs-latency-journal_begin.patch
+ features/fs-reiserfs-bitmap-block-optimization.patch
+ features/fs-reiserfs-bitmap-block-cleanup.patch
+ features/fs-reiserfs-bitmap-reorganize.patch
+ features/fs-reiserfs-bitmap-on-demand-loading.patch