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() ...
This commit is contained in:
@@ -221,7 +221,7 @@ restart:
|
||||
goto restart;
|
||||
}
|
||||
if (buffer_locked(bh)) {
|
||||
atomic_inc(&bh->b_count);
|
||||
get_bh(bh);
|
||||
spin_unlock(&journal->j_list_lock);
|
||||
jbd_unlock_bh_state(bh);
|
||||
wait_on_buffer(bh);
|
||||
@@ -283,7 +283,7 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh,
|
||||
int ret = 0;
|
||||
|
||||
if (buffer_locked(bh)) {
|
||||
atomic_inc(&bh->b_count);
|
||||
get_bh(bh);
|
||||
spin_unlock(&journal->j_list_lock);
|
||||
jbd_unlock_bh_state(bh);
|
||||
wait_on_buffer(bh);
|
||||
|
||||
@@ -587,13 +587,13 @@ void journal_commit_transaction(journal_t *journal)
|
||||
/* Bump b_count to prevent truncate from stumbling over
|
||||
the shadowed buffer! @@@ This can go if we ever get
|
||||
rid of the BJ_IO/BJ_Shadow pairing of buffers. */
|
||||
atomic_inc(&jh2bh(jh)->b_count);
|
||||
get_bh(jh2bh(jh));
|
||||
|
||||
/* Make a temporary IO buffer with which to write it out
|
||||
(this will requeue both the metadata buffer and the
|
||||
temporary IO buffer). new_bh goes on BJ_IO*/
|
||||
|
||||
set_bit(BH_JWrite, &jh2bh(jh)->b_state);
|
||||
set_buffer_jwrite(jh2bh(jh));
|
||||
/*
|
||||
* akpm: journal_write_metadata_buffer() sets
|
||||
* new_bh->b_transaction to commit_transaction.
|
||||
@@ -603,7 +603,7 @@ void journal_commit_transaction(journal_t *journal)
|
||||
JBUFFER_TRACE(jh, "ph3: write metadata");
|
||||
flags = journal_write_metadata_buffer(commit_transaction,
|
||||
jh, &new_jh, blocknr);
|
||||
set_bit(BH_JWrite, &jh2bh(new_jh)->b_state);
|
||||
set_buffer_jwrite(jh2bh(new_jh));
|
||||
wbuf[bufs++] = jh2bh(new_jh);
|
||||
|
||||
/* Record the new block's tag in the current descriptor
|
||||
@@ -713,7 +713,7 @@ wait_for_iobuf:
|
||||
shadowed buffer */
|
||||
jh = commit_transaction->t_shadow_list->b_tprev;
|
||||
bh = jh2bh(jh);
|
||||
clear_bit(BH_JWrite, &bh->b_state);
|
||||
clear_buffer_jwrite(bh);
|
||||
J_ASSERT_BH(bh, buffer_jbddirty(bh));
|
||||
|
||||
/* The metadata is now released for reuse, but we need
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -296,10 +296,10 @@ int journal_skip_recovery(journal_t *journal)
|
||||
#ifdef CONFIG_JBD_DEBUG
|
||||
int dropped = info.end_transaction -
|
||||
be32_to_cpu(journal->j_superblock->s_sequence);
|
||||
#endif
|
||||
jbd_debug(1,
|
||||
"JBD: ignoring %d transaction%s from the journal.\n",
|
||||
dropped, (dropped == 1) ? "" : "s");
|
||||
#endif
|
||||
journal->j_transaction_sequence = ++info.end_transaction;
|
||||
}
|
||||
|
||||
|
||||
@@ -293,9 +293,7 @@ handle_t *journal_start(journal_t *journal, int nblocks)
|
||||
jbd_free_handle(handle);
|
||||
current->journal_info = NULL;
|
||||
handle = ERR_PTR(err);
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
return handle;
|
||||
}
|
||||
|
||||
@@ -528,7 +526,7 @@ do_get_write_access(handle_t *handle, struct journal_head *jh,
|
||||
transaction = handle->h_transaction;
|
||||
journal = transaction->t_journal;
|
||||
|
||||
jbd_debug(5, "buffer_head %p, force_copy %d\n", jh, force_copy);
|
||||
jbd_debug(5, "journal_head %p, force_copy %d\n", jh, force_copy);
|
||||
|
||||
JBUFFER_TRACE(jh, "entry");
|
||||
repeat:
|
||||
@@ -713,7 +711,7 @@ done:
|
||||
J_EXPECT_JH(jh, buffer_uptodate(jh2bh(jh)),
|
||||
"Possible IO failure.\n");
|
||||
page = jh2bh(jh)->b_page;
|
||||
offset = ((unsigned long) jh2bh(jh)->b_data) & ~PAGE_MASK;
|
||||
offset = offset_in_page(jh2bh(jh)->b_data);
|
||||
source = kmap_atomic(page, KM_USER0);
|
||||
memcpy(jh->b_frozen_data, source+offset, jh2bh(jh)->b_size);
|
||||
kunmap_atomic(source, KM_USER0);
|
||||
|
||||
Reference in New Issue
Block a user