History

[PATCH] Manage jbd allocations from its own slabs

JBD currently allocates commit and frozen buffers from slabs. With CONFIG_SLAB_DEBUG, its possible for an allocation to cross the page boundary causing IO problems. https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=200127 So, instead of allocating these from regular slabs - manage allocation from its own slabs and disable slab debug for these slabs. [akpm@osdl.org: cleanups] Signed-off-by: Badari Pulavarty <pbadari@us.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>

Badari Pulavarty committed 20 years ago

Commit ea817391 parent 4c4d50f4 files · +97 −13Browse files

Unified · Split

4 files
  1. fs/jbd/commit.c +3 −3
  2. fs/jbd/journal.c +86 −6
  3. fs/jbd/transaction.c +5 −4
  4. include/linux/jbd.h +3 −0
fs/jbd/commit.c+3−3
@@ -261,7 +261,7 @@ void journal_commit_transaction(journal_t *journal) · 260 unmodified lines
261261 struct buffer_head *bh = jh2bh(jh);
262262
263263 jbd_lock_bh_state(bh);
264− kfree(jh->b_committed_data);
264+ jbd_slab_free(jh->b_committed_data, bh->b_size);
265265 jh->b_committed_data = NULL;
266266 jbd_unlock_bh_state(bh);
267267 }
@@ -745,14 +745,14 @@ restart_loop: · 477 unmodified lines
745745 * Otherwise, we can just throw away the frozen data now.
746746 */
747747 if (jh->b_committed_data) {
748− kfree(jh->b_committed_data);
748+ jbd_slab_free(jh->b_committed_data, bh->b_size);
749749 jh->b_committed_data = NULL;
750750 if (jh->b_frozen_data) {
751751 jh->b_committed_data = jh->b_frozen_data;
752752 jh->b_frozen_data = NULL;
753753 }
754754 } else if (jh->b_frozen_data) {
755− kfree(jh->b_frozen_data);
755+ jbd_slab_free(jh->b_frozen_data, bh->b_size);
756756 jh->b_frozen_data = NULL;
757757 }
758758
fs/jbd/journal.c+86−6
@@ -84,6 +84,7 @@ EXPORT_SYMBOL(journal_force_commit); · 83 unmodified lines
8484
8585 static int journal_convert_superblock_v1(journal_t *, journal_superblock_t *);
8686 static void __journal_abort_soft (journal_t *journal, int errno);
87+static int journal_create_jbd_slab(size_t slab_size);
8788
8889 /*
8990 * Helper function used to manage commit timeouts
@@ -328,10 +329,10 @@ repeat: · 238 unmodified lines
328329 char *tmp;
329330
330331 jbd_unlock_bh_state(bh_in);
331− tmp = jbd_rep_kmalloc(bh_in->b_size, GFP_NOFS);
332+ tmp = jbd_slab_alloc(bh_in->b_size, GFP_NOFS);
332333 jbd_lock_bh_state(bh_in);
333334 if (jh_in->b_frozen_data) {
334− kfree(tmp);
335+ jbd_slab_free(tmp, bh_in->b_size);
335336 goto repeat;
336337 }
337338
@@ -1069,17 +1070,17 @@ static int load_superblock(journal_t *journal) · 731 unmodified lines
10691070 int journal_load(journal_t *journal)
10701071 {
10711072 int err;
1073+ journal_superblock_t *sb;
10721074
10731075 err = load_superblock(journal);
10741076 if (err)
10751077 return err;
10761078
1079+ sb = journal->j_superblock;
10771080 /* If this is a V2 superblock, then we have to check the
10781081 * features flags on it. */
10791082
10801083 if (journal->j_format_version >= 2) {
1081− journal_superblock_t *sb = journal->j_superblock;
1082−
10831084 if ((sb->s_feature_ro_compat &
10841085 ~cpu_to_be32(JFS_KNOWN_ROCOMPAT_FEATURES)) ||
10851086 (sb->s_feature_incompat &
@@ -1090,6 +1091,13 @@ int journal_load(journal_t *journal) · 4 unmodified lines
10901091 }
10911092 }
10921093
1094+ /*
1095+ * Create a slab for this blocksize
1096+ */
1097+ err = journal_create_jbd_slab(cpu_to_be32(sb->s_blocksize));
1098+ if (err)
1099+ return err;
1100+
10931101 /* Let the recovery code check whether it needs to recover any
10941102 * data from the journal. */
10951103 if (journal_recover(journal))
@@ -1611,6 +1619,77 @@ void * __jbd_kmalloc (const char *where, size_t size, gfp_t flags, int retry) · 515 unmodified lines
16111619 return kmalloc(size, flags | (retry ? __GFP_NOFAIL : 0));
16121620 }
16131621
1622+/*
1623+ * jbd slab management: create 1k, 2k, 4k, 8k slabs as needed
1624+ * and allocate frozen and commit buffers from these slabs.
1625+ *
1626+ * Reason for doing this is to avoid, SLAB_DEBUG - since it could
1627+ * cause bh to cross page boundary.
1628+ */
1629+
1630+#define JBD_MAX_SLABS 5
1631+#define JBD_SLAB_INDEX(size) (size >> 11)
1632+
1633+static kmem_cache_t *jbd_slab[JBD_MAX_SLABS];
1634+static const char *jbd_slab_names[JBD_MAX_SLABS] = {
1635+ "jbd_1k", "jbd_2k", "jbd_4k", NULL, "jbd_8k"
1636+};
1637+
1638+static void journal_destroy_jbd_slabs(void)
1639+{
1640+ int i;
1641+
1642+ for (i = 0; i < JBD_MAX_SLABS; i++) {
1643+ if (jbd_slab[i])
1644+ kmem_cache_destroy(jbd_slab[i]);
1645+ jbd_slab[i] = NULL;
1646+ }
1647+}
1648+
1649+static int journal_create_jbd_slab(size_t slab_size)
1650+{
1651+ int i = JBD_SLAB_INDEX(slab_size);
1652+
1653+ BUG_ON(i >= JBD_MAX_SLABS);
1654+
1655+ /*
1656+ * Check if we already have a slab created for this size
1657+ */
1658+ if (jbd_slab[i])
1659+ return 0;
1660+
1661+ /*
1662+ * Create a slab and force alignment to be same as slabsize -
1663+ * this will make sure that allocations won't cross the page
1664+ * boundary.
1665+ */
1666+ jbd_slab[i] = kmem_cache_create(jbd_slab_names[i],
1667+ slab_size, slab_size, 0, NULL, NULL);
1668+ if (!jbd_slab[i]) {
1669+ printk(KERN_EMERG "JBD: no memory for jbd_slab cache\n");
1670+ return -ENOMEM;
1671+ }
1672+ return 0;
1673+}
1674+
1675+void * jbd_slab_alloc(size_t size, gfp_t flags)
1676+{
1677+ int idx;
1678+
1679+ idx = JBD_SLAB_INDEX(size);
1680+ BUG_ON(jbd_slab[idx] == NULL);
1681+ return kmem_cache_alloc(jbd_slab[idx], flags | __GFP_NOFAIL);
1682+}
1683+
1684+void jbd_slab_free(void *ptr, size_t size)
1685+{
1686+ int idx;
1687+
1688+ idx = JBD_SLAB_INDEX(size);
1689+ BUG_ON(jbd_slab[idx] == NULL);
1690+ kmem_cache_free(jbd_slab[idx], ptr);
1691+}
1692+
16141693 /*
16151694 * Journal_head storage management
16161695 */
@@ -1799,13 +1878,13 @@ static void __journal_remove_journal_head(struct buffer_head *bh) · 182 unmodified lines
17991878 printk(KERN_WARNING "%s: freeing "
18001879 "b_frozen_data\n",
18011880 __FUNCTION__);
1802− kfree(jh->b_frozen_data);
1881+ jbd_slab_free(jh->b_frozen_data, bh->b_size);
18031882 }
18041883 if (jh->b_committed_data) {
18051884 printk(KERN_WARNING "%s: freeing "
18061885 "b_committed_data\n",
18071886 __FUNCTION__);
1808− kfree(jh->b_committed_data);
1887+ jbd_slab_free(jh->b_committed_data, bh->b_size);
18091888 }
18101889 bh->b_private = NULL;
18111890 jh->b_bh = NULL; /* debug, really */
@@ -1961,6 +2040,7 @@ static void journal_destroy_caches(void) · 149 unmodified lines
19612040 journal_destroy_revoke_caches();
19622041 journal_destroy_journal_head_cache();
19632042 journal_destroy_handle_cache();
2043+ journal_destroy_jbd_slabs();
19642044 }
19652045
19662046 static int __init journal_init(void)
fs/jbd/transaction.c+5−4
@@ -666,8 +666,9 @@ repeat: · 665 unmodified lines
666666 if (!frozen_buffer) {
667667 JBUFFER_TRACE(jh, "allocate memory for buffer");
668668 jbd_unlock_bh_state(bh);
669− frozen_buffer = jbd_kmalloc(jh2bh(jh)->b_size,
670− GFP_NOFS);
669+ frozen_buffer =
670+ jbd_slab_alloc(jh2bh(jh)->b_size,
671+ GFP_NOFS);
671672 if (!frozen_buffer) {
672673 printk(KERN_EMERG
673674 "%s: OOM for frozen_buffer\n",
@@ -879,7 +880,7 @@ int journal_get_undo_access(handle_t *handle, struct buffer_head *bh) · 205 unmodified lines
879880
880881 repeat:
881882 if (!jh->b_committed_data) {
882− committed_data = jbd_kmalloc(jh2bh(jh)->b_size, GFP_NOFS);
883+ committed_data = jbd_slab_alloc(jh2bh(jh)->b_size, GFP_NOFS);
883884 if (!committed_data) {
884885 printk(KERN_EMERG "%s: No memory for committed data\n",
885886 __FUNCTION__);
@@ -906,7 +907,7 @@ repeat: · 20 unmodified lines
906907 out:
907908 journal_put_journal_head(jh);
908909 if (unlikely(committed_data))
909− kfree(committed_data);
910+ jbd_slab_free(committed_data, bh->b_size);
910911 return err;
911912 }
912913
include/linux/jbd.h+3−0
@@ -72,6 +72,9 @@ extern int journal_enable_debug; · 71 unmodified lines
7272 #endif
7373
7474 extern void * __jbd_kmalloc (const char *where, size_t size, gfp_t flags, int retry);
75+extern void * jbd_slab_alloc(size_t size, gfp_t flags);
76+extern void jbd_slab_free(void *ptr, size_t size);
77+
7578 #define jbd_kmalloc(size, flags) \
7679 __jbd_kmalloc(__FUNCTION__, (size), (flags), journal_oom_retry)
7780 #define jbd_rep_kmalloc(size, flags) \

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t