summaryrefslogtreecommitdiff
path: root/fs/reiserfs/journal.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/reiserfs/journal.c')
-rw-r--r--fs/reiserfs/journal.c145
1 files changed, 91 insertions, 54 deletions
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
index f25086aeef5f..4cad9e75ef56 100644
--- a/fs/reiserfs/journal.c
+++ b/fs/reiserfs/journal.c
@@ -615,6 +615,31 @@ static int journal_list_still_alive(struct super_block *s,
return 0;
}
+/*
+ * If page->mapping was null, we failed to truncate this page for
+ * some reason. Most likely because it was truncated after being
+ * logged via data=journal.
+ *
+ * This does a check to see if the buffer belongs to one of these
+ * lost pages before doing the final put_bh. If page->mapping was
+ * null, it tries to free buffers on the page, which should make the
+ * final page_cache_release drop the page from the lru.
+ */
+static void release_buffer_page(struct buffer_head *bh)
+{
+ struct page *page = bh->b_page;
+ if (!page->mapping && !TestSetPageLocked(page)) {
+ page_cache_get(page);
+ put_bh(bh);
+ if (!page->mapping)
+ try_to_free_buffers(page);
+ unlock_page(page);
+ page_cache_release(page);
+ } else {
+ put_bh(bh);
+ }
+}
+
static void reiserfs_end_buffer_io_sync(struct buffer_head *bh, int uptodate)
{
char b[BDEVNAME_SIZE];
@@ -628,8 +653,9 @@ static void reiserfs_end_buffer_io_sync(struct buffer_head *bh, int uptodate)
set_buffer_uptodate(bh);
else
clear_buffer_uptodate(bh);
+
unlock_buffer(bh);
- put_bh(bh);
+ release_buffer_page(bh);
}
static void reiserfs_end_ordered_io(struct buffer_head *bh, int uptodate)
@@ -966,7 +992,8 @@ static int flush_older_commits(struct super_block *s,
}
return 0;
}
-int reiserfs_async_progress_wait(struct super_block *s)
+
+static int reiserfs_async_progress_wait(struct super_block *s)
{
DEFINE_WAIT(wait);
struct reiserfs_journal *j = SB_JOURNAL(s);
@@ -1546,9 +1573,10 @@ static int flush_journal_list(struct super_block *s,
BUG_ON(!test_clear_buffer_journal_dirty
(cn->bh));
- /* undo the inc from journal_mark_dirty */
+ /* drop one ref for us */
put_bh(cn->bh);
- brelse(cn->bh);
+ /* drop one ref for journal_mark_dirty */
+ release_buffer_page(cn->bh);
}
cn = cn->next;
}
@@ -2621,6 +2649,61 @@ static int journal_init_dev(struct super_block *super,
return result;
}
+/**
+ * When creating/tuning a file system user can assign some
+ * journal params within boundaries which depend on the ratio
+ * blocksize/standard_blocksize.
+ *
+ * For blocks >= standard_blocksize transaction size should
+ * be not less then JOURNAL_TRANS_MIN_DEFAULT, and not more
+ * then JOURNAL_TRANS_MAX_DEFAULT.
+ *
+ * For blocks < standard_blocksize these boundaries should be
+ * decreased proportionally.
+ */
+#define REISERFS_STANDARD_BLKSIZE (4096)
+
+static int check_advise_trans_params(struct super_block *p_s_sb,
+ struct reiserfs_journal *journal)
+{
+ if (journal->j_trans_max) {
+ /* Non-default journal params.
+ Do sanity check for them. */
+ int ratio = 1;
+ if (p_s_sb->s_blocksize < REISERFS_STANDARD_BLKSIZE)
+ ratio = REISERFS_STANDARD_BLKSIZE / p_s_sb->s_blocksize;
+
+ if (journal->j_trans_max > JOURNAL_TRANS_MAX_DEFAULT / ratio ||
+ journal->j_trans_max < JOURNAL_TRANS_MIN_DEFAULT / ratio ||
+ SB_ONDISK_JOURNAL_SIZE(p_s_sb) / journal->j_trans_max <
+ JOURNAL_MIN_RATIO) {
+ reiserfs_warning(p_s_sb,
+ "sh-462: bad transaction max size (%u). FSCK?",
+ journal->j_trans_max);
+ return 1;
+ }
+ if (journal->j_max_batch != (journal->j_trans_max) *
+ JOURNAL_MAX_BATCH_DEFAULT/JOURNAL_TRANS_MAX_DEFAULT) {
+ reiserfs_warning(p_s_sb,
+ "sh-463: bad transaction max batch (%u). FSCK?",
+ journal->j_max_batch);
+ return 1;
+ }
+ } else {
+ /* Default journal params.
+ The file system was created by old version
+ of mkreiserfs, so some fields contain zeros,
+ and we need to advise proper values for them */
+ if (p_s_sb->s_blocksize != REISERFS_STANDARD_BLKSIZE)
+ reiserfs_panic(p_s_sb, "sh-464: bad blocksize (%u)",
+ p_s_sb->s_blocksize);
+ journal->j_trans_max = JOURNAL_TRANS_MAX_DEFAULT;
+ journal->j_max_batch = JOURNAL_MAX_BATCH_DEFAULT;
+ journal->j_max_commit_age = JOURNAL_MAX_COMMIT_AGE;
+ }
+ return 0;
+}
+
/*
** must be called once on fs mount. calls journal_read for you
*/
@@ -2716,49 +2799,8 @@ int journal_init(struct super_block *p_s_sb, const char *j_dev_name,
le32_to_cpu(jh->jh_journal.jp_journal_max_commit_age);
journal->j_max_trans_age = JOURNAL_MAX_TRANS_AGE;
- if (journal->j_trans_max) {
- /* make sure these parameters are available, assign it if they are not */
- __u32 initial = journal->j_trans_max;
- __u32 ratio = 1;
-
- if (p_s_sb->s_blocksize < 4096)
- ratio = 4096 / p_s_sb->s_blocksize;
-
- if (SB_ONDISK_JOURNAL_SIZE(p_s_sb) / journal->j_trans_max <
- JOURNAL_MIN_RATIO)
- journal->j_trans_max =
- SB_ONDISK_JOURNAL_SIZE(p_s_sb) / JOURNAL_MIN_RATIO;
- if (journal->j_trans_max > JOURNAL_TRANS_MAX_DEFAULT / ratio)
- journal->j_trans_max =
- JOURNAL_TRANS_MAX_DEFAULT / ratio;
- if (journal->j_trans_max < JOURNAL_TRANS_MIN_DEFAULT / ratio)
- journal->j_trans_max =
- JOURNAL_TRANS_MIN_DEFAULT / ratio;
-
- if (journal->j_trans_max != initial)
- reiserfs_warning(p_s_sb,
- "sh-461: journal_init: wrong transaction max size (%u). Changed to %u",
- initial, journal->j_trans_max);
-
- journal->j_max_batch = journal->j_trans_max *
- JOURNAL_MAX_BATCH_DEFAULT / JOURNAL_TRANS_MAX_DEFAULT;
- }
-
- if (!journal->j_trans_max) {
- /*we have the file system was created by old version of mkreiserfs
- so this field contains zero value */
- journal->j_trans_max = JOURNAL_TRANS_MAX_DEFAULT;
- journal->j_max_batch = JOURNAL_MAX_BATCH_DEFAULT;
- journal->j_max_commit_age = JOURNAL_MAX_COMMIT_AGE;
-
- /* for blocksize >= 4096 - max transaction size is 1024. For block size < 4096
- trans max size is decreased proportionally */
- if (p_s_sb->s_blocksize < 4096) {
- journal->j_trans_max /= (4096 / p_s_sb->s_blocksize);
- journal->j_max_batch = (journal->j_trans_max) * 9 / 10;
- }
- }
-
+ if (check_advise_trans_params(p_s_sb, journal) != 0)
+ goto free_and_return;
journal->j_default_max_commit_age = journal->j_max_commit_age;
if (commit_max_age != 0) {
@@ -3708,13 +3750,8 @@ int journal_mark_freed(struct reiserfs_transaction_handle *th,
}
}
- if (bh) {
- put_bh(bh); /* get_hash grabs the buffer */
- if (atomic_read(&(bh->b_count)) < 0) {
- reiserfs_warning(p_s_sb,
- "journal-2165: bh->b_count < 0");
- }
- }
+ if (bh)
+ release_buffer_page(bh); /* get_hash grabs the buffer */
return 0;
}