diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-27 20:13:18 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-27 20:13:18 -0700 |
commit | 7d2f280e75f05919314e250cadf361a327ed555c (patch) | |
tree | 47db5a9a0ceaf31adf49c18b663b1e08184f7cff /fs/jbd/journal.c | |
parent | e3e1288e86a07cdeb0aee5860a2dff111c6eff79 (diff) | |
parent | 4408ea41c0ab4b711d4da44dd954fb06dce6c3f8 (diff) | |
download | linux-7d2f280e75f05919314e250cadf361a327ed555c.tar.gz linux-7d2f280e75f05919314e250cadf361a327ed555c.tar.bz2 linux-7d2f280e75f05919314e250cadf361a327ed555c.zip |
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs-2.6
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs-2.6: (24 commits)
quota: Fix possible oops in __dquot_initialize()
ext3: Update kernel-doc comments
jbd/2: fixed typos
ext2: fixed typo.
ext3: Fix debug messages in ext3_group_extend()
jbd: Convert atomic_inc() to get_bh()
ext3: Remove misplaced BUFFER_TRACE() in ext3_truncate()
jbd: Fix debug message in do_get_write_access()
jbd: Check return value of __getblk()
ext3: Use DIV_ROUND_UP() on group desc block counting
ext3: Return proper error code on ext3_fill_super()
ext3: Remove unnecessary casts on bh->b_data
ext3: Cleanup ext3_setup_super()
quota: Fix issuing of warnings from dquot_transfer
quota: fix dquot_disable vs dquot_transfer race v2
jbd: Convert bitops to buffer fns
ext3/jbd: Avoid WARN() messages when failing to write the superblock
jbd: Use offset_in_page() instead of manual calculation
jbd: Remove unnecessary goto statement
jbd: Use printk_ratelimited() in journal_alloc_journal_head()
...
Diffstat (limited to 'fs/jbd/journal.c')
-rw-r--r-- | fs/jbd/journal.c | 44 |
1 files changed, 35 insertions, 9 deletions
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c index 2c4b1f109da9..da1b5e4ffce1 100644 --- a/fs/jbd/journal.c +++ b/fs/jbd/journal.c @@ -36,6 +36,7 @@ #include <linux/poison.h> #include <linux/proc_fs.h> #include <linux/debugfs.h> +#include <linux/ratelimit.h> #include <asm/uaccess.h> #include <asm/page.h> @@ -84,6 +85,7 @@ EXPORT_SYMBOL(journal_force_commit); static int journal_convert_superblock_v1(journal_t *, journal_superblock_t *); static void __journal_abort_soft (journal_t *journal, int errno); +static const char *journal_dev_name(journal_t *journal, char *buffer); /* * Helper function used to manage commit timeouts @@ -439,7 +441,7 @@ int __log_start_commit(journal_t *journal, tid_t target) */ if (!tid_geq(journal->j_commit_request, target)) { /* - * We want a new commit: OK, mark the request and wakup the + * We want a new commit: OK, mark the request and wakeup the * commit thread. We do _not_ do the commit ourselves. */ @@ -950,6 +952,8 @@ int journal_create(journal_t *journal) if (err) return err; bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize); + if (unlikely(!bh)) + return -ENOMEM; lock_buffer(bh); memset (bh->b_data, 0, journal->j_blocksize); BUFFER_TRACE(bh, "marking dirty"); @@ -1010,6 +1014,23 @@ void journal_update_superblock(journal_t *journal, int wait) goto out; } + if (buffer_write_io_error(bh)) { + char b[BDEVNAME_SIZE]; + /* + * Oh, dear. A previous attempt to write the journal + * superblock failed. This could happen because the + * USB device was yanked out. Or it could happen to + * be a transient write error and maybe the block will + * be remapped. Nothing we can do but to retry the + * write and hope for the best. + */ + printk(KERN_ERR "JBD: previous I/O error detected " + "for journal superblock update for %s.\n", + journal_dev_name(journal, b)); + clear_buffer_write_io_error(bh); + set_buffer_uptodate(bh); + } + spin_lock(&journal->j_state_lock); jbd_debug(1,"JBD: updating superblock (start %u, seq %d, errno %d)\n", journal->j_tail, journal->j_tail_sequence, journal->j_errno); @@ -1021,9 +1042,17 @@ void journal_update_superblock(journal_t *journal, int wait) BUFFER_TRACE(bh, "marking dirty"); mark_buffer_dirty(bh); - if (wait) + if (wait) { sync_dirty_buffer(bh); - else + if (buffer_write_io_error(bh)) { + char b[BDEVNAME_SIZE]; + printk(KERN_ERR "JBD: I/O error detected " + "when updating journal superblock for %s.\n", + journal_dev_name(journal, b)); + clear_buffer_write_io_error(bh); + set_buffer_uptodate(bh); + } + } else write_dirty_buffer(bh, WRITE); out: @@ -1719,7 +1748,6 @@ static void journal_destroy_journal_head_cache(void) static struct journal_head *journal_alloc_journal_head(void) { struct journal_head *ret; - static unsigned long last_warning; #ifdef CONFIG_JBD_DEBUG atomic_inc(&nr_journal_heads); @@ -1727,11 +1755,9 @@ static struct journal_head *journal_alloc_journal_head(void) ret = kmem_cache_alloc(journal_head_cache, GFP_NOFS); if (ret == NULL) { jbd_debug(1, "out of memory for journal_head\n"); - if (time_after(jiffies, last_warning + 5*HZ)) { - printk(KERN_NOTICE "ENOMEM in %s, retrying.\n", - __func__); - last_warning = jiffies; - } + printk_ratelimited(KERN_NOTICE "ENOMEM in %s, retrying.\n", + __func__); + while (ret == NULL) { yield(); ret = kmem_cache_alloc(journal_head_cache, GFP_NOFS); |