diff options
Diffstat (limited to 'fs/jbd/journal.c')
-rw-r--r-- | fs/jbd/journal.c | 177 |
1 files changed, 33 insertions, 144 deletions
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c index 06ab3c10b1b8..5d14243499d4 100644 --- a/fs/jbd/journal.c +++ b/fs/jbd/journal.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/kthread.h> | 35 | #include <linux/kthread.h> |
36 | #include <linux/poison.h> | 36 | #include <linux/poison.h> |
37 | #include <linux/proc_fs.h> | 37 | #include <linux/proc_fs.h> |
38 | #include <linux/debugfs.h> | ||
38 | 39 | ||
39 | #include <asm/uaccess.h> | 40 | #include <asm/uaccess.h> |
40 | #include <asm/page.h> | 41 | #include <asm/page.h> |
@@ -83,7 +84,6 @@ EXPORT_SYMBOL(journal_force_commit); | |||
83 | 84 | ||
84 | static int journal_convert_superblock_v1(journal_t *, journal_superblock_t *); | 85 | static int journal_convert_superblock_v1(journal_t *, journal_superblock_t *); |
85 | static void __journal_abort_soft (journal_t *journal, int errno); | 86 | static void __journal_abort_soft (journal_t *journal, int errno); |
86 | static int journal_create_jbd_slab(size_t slab_size); | ||
87 | 87 | ||
88 | /* | 88 | /* |
89 | * Helper function used to manage commit timeouts | 89 | * Helper function used to manage commit timeouts |
@@ -218,7 +218,7 @@ static int journal_start_thread(journal_t *journal) | |||
218 | if (IS_ERR(t)) | 218 | if (IS_ERR(t)) |
219 | return PTR_ERR(t); | 219 | return PTR_ERR(t); |
220 | 220 | ||
221 | wait_event(journal->j_wait_done_commit, journal->j_task != 0); | 221 | wait_event(journal->j_wait_done_commit, journal->j_task != NULL); |
222 | return 0; | 222 | return 0; |
223 | } | 223 | } |
224 | 224 | ||
@@ -230,7 +230,8 @@ static void journal_kill_thread(journal_t *journal) | |||
230 | while (journal->j_task) { | 230 | while (journal->j_task) { |
231 | wake_up(&journal->j_wait_commit); | 231 | wake_up(&journal->j_wait_commit); |
232 | spin_unlock(&journal->j_state_lock); | 232 | spin_unlock(&journal->j_state_lock); |
233 | wait_event(journal->j_wait_done_commit, journal->j_task == 0); | 233 | wait_event(journal->j_wait_done_commit, |
234 | journal->j_task == NULL); | ||
234 | spin_lock(&journal->j_state_lock); | 235 | spin_lock(&journal->j_state_lock); |
235 | } | 236 | } |
236 | spin_unlock(&journal->j_state_lock); | 237 | spin_unlock(&journal->j_state_lock); |
@@ -334,10 +335,10 @@ repeat: | |||
334 | char *tmp; | 335 | char *tmp; |
335 | 336 | ||
336 | jbd_unlock_bh_state(bh_in); | 337 | jbd_unlock_bh_state(bh_in); |
337 | tmp = jbd_slab_alloc(bh_in->b_size, GFP_NOFS); | 338 | tmp = jbd_alloc(bh_in->b_size, GFP_NOFS); |
338 | jbd_lock_bh_state(bh_in); | 339 | jbd_lock_bh_state(bh_in); |
339 | if (jh_in->b_frozen_data) { | 340 | if (jh_in->b_frozen_data) { |
340 | jbd_slab_free(tmp, bh_in->b_size); | 341 | jbd_free(tmp, bh_in->b_size); |
341 | goto repeat; | 342 | goto repeat; |
342 | } | 343 | } |
343 | 344 | ||
@@ -654,10 +655,9 @@ static journal_t * journal_init_common (void) | |||
654 | journal_t *journal; | 655 | journal_t *journal; |
655 | int err; | 656 | int err; |
656 | 657 | ||
657 | journal = jbd_kmalloc(sizeof(*journal), GFP_KERNEL); | 658 | journal = kzalloc(sizeof(*journal), GFP_KERNEL); |
658 | if (!journal) | 659 | if (!journal) |
659 | goto fail; | 660 | goto fail; |
660 | memset(journal, 0, sizeof(*journal)); | ||
661 | 661 | ||
662 | init_waitqueue_head(&journal->j_wait_transaction_locked); | 662 | init_waitqueue_head(&journal->j_wait_transaction_locked); |
663 | init_waitqueue_head(&journal->j_wait_logspace); | 663 | init_waitqueue_head(&journal->j_wait_logspace); |
@@ -1095,13 +1095,6 @@ int journal_load(journal_t *journal) | |||
1095 | } | 1095 | } |
1096 | } | 1096 | } |
1097 | 1097 | ||
1098 | /* | ||
1099 | * Create a slab for this blocksize | ||
1100 | */ | ||
1101 | err = journal_create_jbd_slab(be32_to_cpu(sb->s_blocksize)); | ||
1102 | if (err) | ||
1103 | return err; | ||
1104 | |||
1105 | /* Let the recovery code check whether it needs to recover any | 1098 | /* Let the recovery code check whether it needs to recover any |
1106 | * data from the journal. */ | 1099 | * data from the journal. */ |
1107 | if (journal_recover(journal)) | 1100 | if (journal_recover(journal)) |
@@ -1615,86 +1608,6 @@ int journal_blocks_per_page(struct inode *inode) | |||
1615 | } | 1608 | } |
1616 | 1609 | ||
1617 | /* | 1610 | /* |
1618 | * Simple support for retrying memory allocations. Introduced to help to | ||
1619 | * debug different VM deadlock avoidance strategies. | ||
1620 | */ | ||
1621 | void * __jbd_kmalloc (const char *where, size_t size, gfp_t flags, int retry) | ||
1622 | { | ||
1623 | return kmalloc(size, flags | (retry ? __GFP_NOFAIL : 0)); | ||
1624 | } | ||
1625 | |||
1626 | /* | ||
1627 | * jbd slab management: create 1k, 2k, 4k, 8k slabs as needed | ||
1628 | * and allocate frozen and commit buffers from these slabs. | ||
1629 | * | ||
1630 | * Reason for doing this is to avoid, SLAB_DEBUG - since it could | ||
1631 | * cause bh to cross page boundary. | ||
1632 | */ | ||
1633 | |||
1634 | #define JBD_MAX_SLABS 5 | ||
1635 | #define JBD_SLAB_INDEX(size) (size >> 11) | ||
1636 | |||
1637 | static struct kmem_cache *jbd_slab[JBD_MAX_SLABS]; | ||
1638 | static const char *jbd_slab_names[JBD_MAX_SLABS] = { | ||
1639 | "jbd_1k", "jbd_2k", "jbd_4k", NULL, "jbd_8k" | ||
1640 | }; | ||
1641 | |||
1642 | static void journal_destroy_jbd_slabs(void) | ||
1643 | { | ||
1644 | int i; | ||
1645 | |||
1646 | for (i = 0; i < JBD_MAX_SLABS; i++) { | ||
1647 | if (jbd_slab[i]) | ||
1648 | kmem_cache_destroy(jbd_slab[i]); | ||
1649 | jbd_slab[i] = NULL; | ||
1650 | } | ||
1651 | } | ||
1652 | |||
1653 | static int journal_create_jbd_slab(size_t slab_size) | ||
1654 | { | ||
1655 | int i = JBD_SLAB_INDEX(slab_size); | ||
1656 | |||
1657 | BUG_ON(i >= JBD_MAX_SLABS); | ||
1658 | |||
1659 | /* | ||
1660 | * Check if we already have a slab created for this size | ||
1661 | */ | ||
1662 | if (jbd_slab[i]) | ||
1663 | return 0; | ||
1664 | |||
1665 | /* | ||
1666 | * Create a slab and force alignment to be same as slabsize - | ||
1667 | * this will make sure that allocations won't cross the page | ||
1668 | * boundary. | ||
1669 | */ | ||
1670 | jbd_slab[i] = kmem_cache_create(jbd_slab_names[i], | ||
1671 | slab_size, slab_size, 0, NULL); | ||
1672 | if (!jbd_slab[i]) { | ||
1673 | printk(KERN_EMERG "JBD: no memory for jbd_slab cache\n"); | ||
1674 | return -ENOMEM; | ||
1675 | } | ||
1676 | return 0; | ||
1677 | } | ||
1678 | |||
1679 | void * jbd_slab_alloc(size_t size, gfp_t flags) | ||
1680 | { | ||
1681 | int idx; | ||
1682 | |||
1683 | idx = JBD_SLAB_INDEX(size); | ||
1684 | BUG_ON(jbd_slab[idx] == NULL); | ||
1685 | return kmem_cache_alloc(jbd_slab[idx], flags | __GFP_NOFAIL); | ||
1686 | } | ||
1687 | |||
1688 | void jbd_slab_free(void *ptr, size_t size) | ||
1689 | { | ||
1690 | int idx; | ||
1691 | |||
1692 | idx = JBD_SLAB_INDEX(size); | ||
1693 | BUG_ON(jbd_slab[idx] == NULL); | ||
1694 | kmem_cache_free(jbd_slab[idx], ptr); | ||
1695 | } | ||
1696 | |||
1697 | /* | ||
1698 | * Journal_head storage management | 1611 | * Journal_head storage management |
1699 | */ | 1612 | */ |
1700 | static struct kmem_cache *journal_head_cache; | 1613 | static struct kmem_cache *journal_head_cache; |
@@ -1710,7 +1623,7 @@ static int journal_init_journal_head_cache(void) | |||
1710 | journal_head_cache = kmem_cache_create("journal_head", | 1623 | journal_head_cache = kmem_cache_create("journal_head", |
1711 | sizeof(struct journal_head), | 1624 | sizeof(struct journal_head), |
1712 | 0, /* offset */ | 1625 | 0, /* offset */ |
1713 | 0, /* flags */ | 1626 | SLAB_TEMPORARY, /* flags */ |
1714 | NULL); /* ctor */ | 1627 | NULL); /* ctor */ |
1715 | retval = 0; | 1628 | retval = 0; |
1716 | if (journal_head_cache == 0) { | 1629 | if (journal_head_cache == 0) { |
@@ -1739,14 +1652,14 @@ static struct journal_head *journal_alloc_journal_head(void) | |||
1739 | atomic_inc(&nr_journal_heads); | 1652 | atomic_inc(&nr_journal_heads); |
1740 | #endif | 1653 | #endif |
1741 | ret = kmem_cache_alloc(journal_head_cache, GFP_NOFS); | 1654 | ret = kmem_cache_alloc(journal_head_cache, GFP_NOFS); |
1742 | if (ret == 0) { | 1655 | if (ret == NULL) { |
1743 | jbd_debug(1, "out of memory for journal_head\n"); | 1656 | jbd_debug(1, "out of memory for journal_head\n"); |
1744 | if (time_after(jiffies, last_warning + 5*HZ)) { | 1657 | if (time_after(jiffies, last_warning + 5*HZ)) { |
1745 | printk(KERN_NOTICE "ENOMEM in %s, retrying.\n", | 1658 | printk(KERN_NOTICE "ENOMEM in %s, retrying.\n", |
1746 | __FUNCTION__); | 1659 | __FUNCTION__); |
1747 | last_warning = jiffies; | 1660 | last_warning = jiffies; |
1748 | } | 1661 | } |
1749 | while (ret == 0) { | 1662 | while (ret == NULL) { |
1750 | yield(); | 1663 | yield(); |
1751 | ret = kmem_cache_alloc(journal_head_cache, GFP_NOFS); | 1664 | ret = kmem_cache_alloc(journal_head_cache, GFP_NOFS); |
1752 | } | 1665 | } |
@@ -1881,13 +1794,13 @@ static void __journal_remove_journal_head(struct buffer_head *bh) | |||
1881 | printk(KERN_WARNING "%s: freeing " | 1794 | printk(KERN_WARNING "%s: freeing " |
1882 | "b_frozen_data\n", | 1795 | "b_frozen_data\n", |
1883 | __FUNCTION__); | 1796 | __FUNCTION__); |
1884 | jbd_slab_free(jh->b_frozen_data, bh->b_size); | 1797 | jbd_free(jh->b_frozen_data, bh->b_size); |
1885 | } | 1798 | } |
1886 | if (jh->b_committed_data) { | 1799 | if (jh->b_committed_data) { |
1887 | printk(KERN_WARNING "%s: freeing " | 1800 | printk(KERN_WARNING "%s: freeing " |
1888 | "b_committed_data\n", | 1801 | "b_committed_data\n", |
1889 | __FUNCTION__); | 1802 | __FUNCTION__); |
1890 | jbd_slab_free(jh->b_committed_data, bh->b_size); | 1803 | jbd_free(jh->b_committed_data, bh->b_size); |
1891 | } | 1804 | } |
1892 | bh->b_private = NULL; | 1805 | bh->b_private = NULL; |
1893 | jh->b_bh = NULL; /* debug, really */ | 1806 | jh->b_bh = NULL; /* debug, really */ |
@@ -1939,64 +1852,41 @@ void journal_put_journal_head(struct journal_head *jh) | |||
1939 | } | 1852 | } |
1940 | 1853 | ||
1941 | /* | 1854 | /* |
1942 | * /proc tunables | 1855 | * debugfs tunables |
1943 | */ | 1856 | */ |
1944 | #if defined(CONFIG_JBD_DEBUG) | 1857 | #ifdef CONFIG_JBD_DEBUG |
1945 | int journal_enable_debug; | ||
1946 | EXPORT_SYMBOL(journal_enable_debug); | ||
1947 | #endif | ||
1948 | 1858 | ||
1949 | #if defined(CONFIG_JBD_DEBUG) && defined(CONFIG_PROC_FS) | 1859 | u8 journal_enable_debug __read_mostly; |
1860 | EXPORT_SYMBOL(journal_enable_debug); | ||
1950 | 1861 | ||
1951 | static struct proc_dir_entry *proc_jbd_debug; | 1862 | static struct dentry *jbd_debugfs_dir; |
1863 | static struct dentry *jbd_debug; | ||
1952 | 1864 | ||
1953 | static int read_jbd_debug(char *page, char **start, off_t off, | 1865 | static void __init jbd_create_debugfs_entry(void) |
1954 | int count, int *eof, void *data) | ||
1955 | { | 1866 | { |
1956 | int ret; | 1867 | jbd_debugfs_dir = debugfs_create_dir("jbd", NULL); |
1957 | 1868 | if (jbd_debugfs_dir) | |
1958 | ret = sprintf(page + off, "%d\n", journal_enable_debug); | 1869 | jbd_debug = debugfs_create_u8("jbd-debug", S_IRUGO, |
1959 | *eof = 1; | 1870 | jbd_debugfs_dir, |
1960 | return ret; | 1871 | &journal_enable_debug); |
1961 | } | 1872 | } |
1962 | 1873 | ||
1963 | static int write_jbd_debug(struct file *file, const char __user *buffer, | 1874 | static void __exit jbd_remove_debugfs_entry(void) |
1964 | unsigned long count, void *data) | ||
1965 | { | 1875 | { |
1966 | char buf[32]; | 1876 | debugfs_remove(jbd_debug); |
1967 | 1877 | debugfs_remove(jbd_debugfs_dir); | |
1968 | if (count > ARRAY_SIZE(buf) - 1) | ||
1969 | count = ARRAY_SIZE(buf) - 1; | ||
1970 | if (copy_from_user(buf, buffer, count)) | ||
1971 | return -EFAULT; | ||
1972 | buf[ARRAY_SIZE(buf) - 1] = '\0'; | ||
1973 | journal_enable_debug = simple_strtoul(buf, NULL, 10); | ||
1974 | return count; | ||
1975 | } | 1878 | } |
1976 | 1879 | ||
1977 | #define JBD_PROC_NAME "sys/fs/jbd-debug" | 1880 | #else |
1978 | 1881 | ||
1979 | static void __init create_jbd_proc_entry(void) | 1882 | static inline void jbd_create_debugfs_entry(void) |
1980 | { | 1883 | { |
1981 | proc_jbd_debug = create_proc_entry(JBD_PROC_NAME, 0644, NULL); | ||
1982 | if (proc_jbd_debug) { | ||
1983 | /* Why is this so hard? */ | ||
1984 | proc_jbd_debug->read_proc = read_jbd_debug; | ||
1985 | proc_jbd_debug->write_proc = write_jbd_debug; | ||
1986 | } | ||
1987 | } | 1884 | } |
1988 | 1885 | ||
1989 | static void __exit remove_jbd_proc_entry(void) | 1886 | static inline void jbd_remove_debugfs_entry(void) |
1990 | { | 1887 | { |
1991 | if (proc_jbd_debug) | ||
1992 | remove_proc_entry(JBD_PROC_NAME, NULL); | ||
1993 | } | 1888 | } |
1994 | 1889 | ||
1995 | #else | ||
1996 | |||
1997 | #define create_jbd_proc_entry() do {} while (0) | ||
1998 | #define remove_jbd_proc_entry() do {} while (0) | ||
1999 | |||
2000 | #endif | 1890 | #endif |
2001 | 1891 | ||
2002 | struct kmem_cache *jbd_handle_cache; | 1892 | struct kmem_cache *jbd_handle_cache; |
@@ -2006,7 +1896,7 @@ static int __init journal_init_handle_cache(void) | |||
2006 | jbd_handle_cache = kmem_cache_create("journal_handle", | 1896 | jbd_handle_cache = kmem_cache_create("journal_handle", |
2007 | sizeof(handle_t), | 1897 | sizeof(handle_t), |
2008 | 0, /* offset */ | 1898 | 0, /* offset */ |
2009 | 0, /* flags */ | 1899 | SLAB_TEMPORARY, /* flags */ |
2010 | NULL); /* ctor */ | 1900 | NULL); /* ctor */ |
2011 | if (jbd_handle_cache == NULL) { | 1901 | if (jbd_handle_cache == NULL) { |
2012 | printk(KERN_EMERG "JBD: failed to create handle cache\n"); | 1902 | printk(KERN_EMERG "JBD: failed to create handle cache\n"); |
@@ -2042,7 +1932,6 @@ static void journal_destroy_caches(void) | |||
2042 | journal_destroy_revoke_caches(); | 1932 | journal_destroy_revoke_caches(); |
2043 | journal_destroy_journal_head_cache(); | 1933 | journal_destroy_journal_head_cache(); |
2044 | journal_destroy_handle_cache(); | 1934 | journal_destroy_handle_cache(); |
2045 | journal_destroy_jbd_slabs(); | ||
2046 | } | 1935 | } |
2047 | 1936 | ||
2048 | static int __init journal_init(void) | 1937 | static int __init journal_init(void) |
@@ -2054,7 +1943,7 @@ static int __init journal_init(void) | |||
2054 | ret = journal_init_caches(); | 1943 | ret = journal_init_caches(); |
2055 | if (ret != 0) | 1944 | if (ret != 0) |
2056 | journal_destroy_caches(); | 1945 | journal_destroy_caches(); |
2057 | create_jbd_proc_entry(); | 1946 | jbd_create_debugfs_entry(); |
2058 | return ret; | 1947 | return ret; |
2059 | } | 1948 | } |
2060 | 1949 | ||
@@ -2065,7 +1954,7 @@ static void __exit journal_exit(void) | |||
2065 | if (n) | 1954 | if (n) |
2066 | printk(KERN_EMERG "JBD: leaked %d journal_heads!\n", n); | 1955 | printk(KERN_EMERG "JBD: leaked %d journal_heads!\n", n); |
2067 | #endif | 1956 | #endif |
2068 | remove_jbd_proc_entry(); | 1957 | jbd_remove_debugfs_entry(); |
2069 | journal_destroy_caches(); | 1958 | journal_destroy_caches(); |
2070 | } | 1959 | } |
2071 | 1960 | ||