aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Kara2019-11-05 17:44:09 +0100
committerTheodore Ts'o2019-11-05 12:13:25 -0500
commitb90bfdf581194a0fa5f6c26fef1e522f15f6212e (patch)
tree049cad17c0b0b24520d734501ad6a1c4a2b05935
parent0db45889453644bb5d3e3c6044f4d81b910d41ef (diff)
jbd2: Completely fill journal descriptor blocks
With 32-bit block numbers, we don't allocate the array for journal buffer heads large enough for corresponding descriptor tags to fill the descriptor block. Thus we end up writing out half-full descriptor blocks to the journal unnecessarily growing the transaction. Fix the logic to allocate the array large enough. Signed-off-by: Jan Kara <jack@suse.cz> Link: https://lore.kernel.org/r/20191105164437.32602-3-jack@suse.cz Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-rw-r--r--fs/jbd2/journal.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
index 1c58859aa592..cc11097f1176 100644
--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -1098,6 +1098,16 @@ static void jbd2_stats_proc_exit(journal_t *journal)
remove_proc_entry(journal->j_devname, proc_jbd2_stats);
}
+/* Minimum size of descriptor tag */
+static int jbd2_min_tag_size(void)
+{
+ /*
+ * Tag with 32-bit block numbers does not use last four bytes of the
+ * structure
+ */
+ return sizeof(journal_block_tag_t) - 4;
+}
+
/*
* Management for journal control blocks: functions to create and
* destroy journal_t structures, and to initialise and read existing
@@ -1156,7 +1166,8 @@ static journal_t *journal_init_common(struct block_device *bdev,
journal->j_fs_dev = fs_dev;
journal->j_blk_offset = start;
journal->j_maxlen = len;
- n = journal->j_blocksize / sizeof(journal_block_tag_t);
+ /* We need enough buffers to write out full descriptor block. */
+ n = journal->j_blocksize / jbd2_min_tag_size();
journal->j_wbufsize = n;
journal->j_wbuf = kmalloc_array(n, sizeof(struct buffer_head *),
GFP_KERNEL);