spin_lock(lock);
goto loop_next;
}
+ /* in theory, dirty non-uptodate buffers should never get here,
+ * but the upper layer io error paths still have a few quirks.
+ * Handle them here as gracefully as we can
+ */
+ if (!buffer_uptodate(bh) && buffer_dirty(bh)) {
+ clear_buffer_dirty(bh);
+ ret = -EIO;
+ }
if (buffer_dirty(bh)) {
list_del_init(&jh->list);
list_add(&jh->list, &tmp);
if (!buffer_uptodate(bh)) {
ret = -EIO;
}
+ /* ugly interaction with invalidatepage here.
+ * reiserfs_invalidate_page will pin any buffer that has a valid
+ * journal head from an older transaction. If someone else sets
+ * our buffer dirty after we write it in the first loop, and
+ * then someone truncates the page away, nobody will ever write
+ * the buffer. We're safe if we write the page one last time
+ * after freeing the journal header.
+ */
+ if (buffer_dirty(bh) && unlikely(bh->b_page->mapping == NULL)) {
+ spin_unlock(lock);
+ ll_rw_block(WRITE, 1, &bh);
+ spin_lock(lock);
+ }
put_bh(bh);
cond_resched_lock(lock);
}
struct reiserfs_journal *journal = SB_JOURNAL(s);
int barrier = 0;
int retval = 0;
+ int write_len;
reiserfs_check_lock_depth(s, "flush_commit_list");
}
if (!list_empty(&jl->j_bh_list)) {
+ int ret;
unlock_kernel();
- write_ordered_buffers(&journal->j_dirty_buffers_lock,
- journal, jl, &jl->j_bh_list);
+ ret = write_ordered_buffers(&journal->j_dirty_buffers_lock,
+ journal, jl, &jl->j_bh_list);
+ if (ret < 0 && retval == 0)
+ retval = ret;
lock_kernel();
}
BUG_ON(!list_empty(&jl->j_bh_list));
/*
* for the description block and all the log blocks, submit any buffers
- * that haven't already reached the disk
+ * that haven't already reached the disk. Try to write at least 256
+ * log blocks. later on, we will only wait on blocks that correspond
+ * to this transaction, but while we're unplugging we might as well
+ * get a chunk of data on there.
*/
atomic_inc(&journal->j_async_throttle);
- for (i = 0; i < (jl->j_len + 1); i++) {
+ write_len = jl->j_len + 1;
+ if (write_len < 256)
+ write_len = 256;
+ for (i = 0 ; i < write_len ; i++) {
bn = SB_ONDISK_JOURNAL_1st_BLOCK(s) + (jl->j_start + i) %
SB_ONDISK_JOURNAL_SIZE(s);
tbh = journal_find_get_block(s, bn);
- if (buffer_dirty(tbh)) /* redundant, ll_rw_block() checks */
- ll_rw_block(SWRITE, 1, &tbh);
- put_bh(tbh);
+ if (tbh) {
+ if (buffer_dirty(tbh))
+ ll_rw_block(WRITE, 1, &tbh) ;
+ put_bh(tbh) ;
+ }
}
atomic_dec(&journal->j_async_throttle);
return 1;
}
jh = (struct reiserfs_journal_header *)(journal->j_header_bh->b_data);
- if (le32_to_cpu(jh->j_first_unflushed_offset) >= 0 &&
- le32_to_cpu(jh->j_first_unflushed_offset) <
+ if (le32_to_cpu(jh->j_first_unflushed_offset) <
SB_ONDISK_JOURNAL_SIZE(p_s_sb)
&& le32_to_cpu(jh->j_last_flush_trans_id) > 0) {
oldest_start =
journal->j_cnode_free < (journal->j_trans_max * 3)) {
return 1;
}
+ /* protected by the BKL here */
+ journal->j_len_alloc += new_alloc;
+ th->t_blocks_allocated += new_alloc ;
return 0;
}