X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=fs%2Freiserfs%2Fjournal.c;h=bc8fe963b3cc57ff671999b5858c4e07d38967d1;hb=d62b1b87a7d1c3a21dddabed4251763090be3182;hp=ca7989b04be3490f1e430cae7af2c1b242e521c8;hpb=2fca877b68b2b4fc5b94277858a1bedd46017cde;p=powerpc.git diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index ca7989b04b..bc8fe963b3 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c @@ -152,18 +152,16 @@ static struct reiserfs_bitmap_node *allocate_bitmap_node(struct super_block struct reiserfs_bitmap_node *bn; static int id; - bn = reiserfs_kmalloc(sizeof(struct reiserfs_bitmap_node), GFP_NOFS, - p_s_sb); + bn = kmalloc(sizeof(struct reiserfs_bitmap_node), GFP_NOFS); if (!bn) { return NULL; } - bn->data = reiserfs_kmalloc(p_s_sb->s_blocksize, GFP_NOFS, p_s_sb); + bn->data = kzalloc(p_s_sb->s_blocksize, GFP_NOFS); if (!bn->data) { - reiserfs_kfree(bn, sizeof(struct reiserfs_bitmap_node), p_s_sb); + kfree(bn); return NULL; } bn->id = id++; - memset(bn->data, 0, p_s_sb->s_blocksize); INIT_LIST_HEAD(&bn->list); return bn; } @@ -197,8 +195,8 @@ static inline void free_bitmap_node(struct super_block *p_s_sb, struct reiserfs_journal *journal = SB_JOURNAL(p_s_sb); journal->j_used_bitmap_nodes--; if (journal->j_free_bitmap_nodes > REISERFS_MAX_BITMAP_NODES) { - reiserfs_kfree(bn->data, p_s_sb->s_blocksize, p_s_sb); - reiserfs_kfree(bn, sizeof(struct reiserfs_bitmap_node), p_s_sb); + kfree(bn->data); + kfree(bn); } else { list_add(&bn->list, &journal->j_bitmap_nodes); journal->j_free_bitmap_nodes++; @@ -276,8 +274,8 @@ static int free_bitmap_nodes(struct super_block *p_s_sb) while (next != &journal->j_bitmap_nodes) { bn = list_entry(next, struct reiserfs_bitmap_node, list); list_del(next); - reiserfs_kfree(bn->data, p_s_sb->s_blocksize, p_s_sb); - reiserfs_kfree(bn, sizeof(struct reiserfs_bitmap_node), p_s_sb); + kfree(bn->data); + kfree(bn); next = journal->j_bitmap_nodes.next; journal->j_free_bitmap_nodes--; } @@ -581,7 +579,7 @@ static inline void put_journal_list(struct super_block *s, jl->j_trans_id, jl->j_refcount); } if (--jl->j_refcount == 0) - reiserfs_kfree(jl, sizeof(struct reiserfs_journal_list), s); + kfree(jl); } /* @@ -879,6 +877,19 @@ static int write_ordered_buffers(spinlock_t * lock, 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); } @@ -1034,11 +1045,15 @@ static int flush_commit_list(struct super_block *s, SB_ONDISK_JOURNAL_SIZE(s); tbh = journal_find_get_block(s, bn); if (buffer_dirty(tbh)) /* redundant, ll_rw_block() checks */ - ll_rw_block(WRITE, 1, &tbh); + ll_rw_block(SWRITE, 1, &tbh); put_bh(tbh); } atomic_dec(&journal->j_async_throttle); + /* We're skipping the commit if there's an error */ + if (retval || reiserfs_is_journal_aborted(journal)) + barrier = 0; + /* wait on everything written so far before writing the commit * if we are in barrier mode, send the commit down now */ @@ -1077,10 +1092,16 @@ static int flush_commit_list(struct super_block *s, BUG_ON(atomic_read(&(jl->j_commit_left)) != 1); if (!barrier) { - if (buffer_dirty(jl->j_commit_bh)) - BUG(); - mark_buffer_dirty(jl->j_commit_bh); - sync_dirty_buffer(jl->j_commit_bh); + /* If there was a write error in the journal - we can't commit + * this transaction - it will be invalid and, if successful, + * will just end up propogating the write error out to + * the file system. */ + if (likely(!retval && !reiserfs_is_journal_aborted (journal))) { + if (buffer_dirty(jl->j_commit_bh)) + BUG(); + mark_buffer_dirty(jl->j_commit_bh) ; + sync_dirty_buffer(jl->j_commit_bh) ; + } } else wait_on_buffer(jl->j_commit_bh); @@ -1808,8 +1829,7 @@ void remove_journal_hash(struct super_block *sb, static void free_journal_ram(struct super_block *p_s_sb) { struct reiserfs_journal *journal = SB_JOURNAL(p_s_sb); - reiserfs_kfree(journal->j_current_jl, - sizeof(struct reiserfs_journal_list), p_s_sb); + kfree(journal->j_current_jl); journal->j_num_lists--; vfree(journal->j_cnode_free_orig); @@ -2083,21 +2103,15 @@ static int journal_read_transaction(struct super_block *p_s_sb, } trans_id = get_desc_trans_id(desc); /* now we know we've got a good transaction, and it was inside the valid time ranges */ - log_blocks = - reiserfs_kmalloc(get_desc_trans_len(desc) * - sizeof(struct buffer_head *), GFP_NOFS, p_s_sb); - real_blocks = - reiserfs_kmalloc(get_desc_trans_len(desc) * - sizeof(struct buffer_head *), GFP_NOFS, p_s_sb); + log_blocks = kmalloc(get_desc_trans_len(desc) * + sizeof(struct buffer_head *), GFP_NOFS); + real_blocks = kmalloc(get_desc_trans_len(desc) * + sizeof(struct buffer_head *), GFP_NOFS); if (!log_blocks || !real_blocks) { brelse(c_bh); brelse(d_bh); - reiserfs_kfree(log_blocks, - get_desc_trans_len(desc) * - sizeof(struct buffer_head *), p_s_sb); - reiserfs_kfree(real_blocks, - get_desc_trans_len(desc) * - sizeof(struct buffer_head *), p_s_sb); + kfree(log_blocks); + kfree(real_blocks); reiserfs_warning(p_s_sb, "journal-1169: kmalloc failed, unable to mount FS"); return -1; @@ -2135,12 +2149,8 @@ static int journal_read_transaction(struct super_block *p_s_sb, brelse_array(real_blocks, i); brelse(c_bh); brelse(d_bh); - reiserfs_kfree(log_blocks, - get_desc_trans_len(desc) * - sizeof(struct buffer_head *), p_s_sb); - reiserfs_kfree(real_blocks, - get_desc_trans_len(desc) * - sizeof(struct buffer_head *), p_s_sb); + kfree(log_blocks); + kfree(real_blocks); return -1; } } @@ -2156,12 +2166,8 @@ static int journal_read_transaction(struct super_block *p_s_sb, brelse_array(real_blocks, get_desc_trans_len(desc)); brelse(c_bh); brelse(d_bh); - reiserfs_kfree(log_blocks, - get_desc_trans_len(desc) * - sizeof(struct buffer_head *), p_s_sb); - reiserfs_kfree(real_blocks, - get_desc_trans_len(desc) * - sizeof(struct buffer_head *), p_s_sb); + kfree(log_blocks); + kfree(real_blocks); return -1; } memcpy(real_blocks[i]->b_data, log_blocks[i]->b_data, @@ -2172,7 +2178,7 @@ static int journal_read_transaction(struct super_block *p_s_sb, /* flush out the real blocks */ for (i = 0; i < get_desc_trans_len(desc); i++) { set_buffer_dirty(real_blocks[i]); - ll_rw_block(WRITE, 1, real_blocks + i); + ll_rw_block(SWRITE, 1, real_blocks + i); } for (i = 0; i < get_desc_trans_len(desc); i++) { wait_on_buffer(real_blocks[i]); @@ -2183,12 +2189,8 @@ static int journal_read_transaction(struct super_block *p_s_sb, get_desc_trans_len(desc) - i); brelse(c_bh); brelse(d_bh); - reiserfs_kfree(log_blocks, - get_desc_trans_len(desc) * - sizeof(struct buffer_head *), p_s_sb); - reiserfs_kfree(real_blocks, - get_desc_trans_len(desc) * - sizeof(struct buffer_head *), p_s_sb); + kfree(log_blocks); + kfree(real_blocks); return -1; } brelse(real_blocks[i]); @@ -2207,12 +2209,8 @@ static int journal_read_transaction(struct super_block *p_s_sb, journal->j_trans_id = trans_id + 1; brelse(c_bh); brelse(d_bh); - reiserfs_kfree(log_blocks, - le32_to_cpu(desc->j_len) * sizeof(struct buffer_head *), - p_s_sb); - reiserfs_kfree(real_blocks, - le32_to_cpu(desc->j_len) * sizeof(struct buffer_head *), - p_s_sb); + kfree(log_blocks); + kfree(real_blocks); return 0; } @@ -2461,14 +2459,8 @@ static int journal_read(struct super_block *p_s_sb) static struct reiserfs_journal_list *alloc_journal_list(struct super_block *s) { struct reiserfs_journal_list *jl; - retry: - jl = reiserfs_kmalloc(sizeof(struct reiserfs_journal_list), GFP_NOFS, - s); - if (!jl) { - yield(); - goto retry; - } - memset(jl, 0, sizeof(*jl)); + jl = kzalloc(sizeof(struct reiserfs_journal_list), + GFP_NOFS | __GFP_NOFAIL); INIT_LIST_HEAD(&jl->j_list); INIT_LIST_HEAD(&jl->j_working_list); INIT_LIST_HEAD(&jl->j_tail_bh_list); @@ -2757,6 +2749,15 @@ int journal_init(struct super_block *p_s_sb, const char *j_dev_name, journal->j_cnode_used = 0; journal->j_must_wait = 0; + if (journal->j_cnode_free == 0) { + reiserfs_warning(p_s_sb, "journal-2004: Journal cnode memory " + "allocation failed (%ld bytes). Journal is " + "too large for available memory. Usually " + "this is due to a journal that is too large.", + sizeof (struct reiserfs_journal_cnode) * num_cnodes); + goto free_and_return; + } + init_journal_hash(p_s_sb); jl = journal->j_current_jl; jl->j_list_bitmap = get_list_bitmap(p_s_sb, jl); @@ -2868,8 +2869,7 @@ static void let_transaction_grow(struct super_block *sb, unsigned long trans_id) struct reiserfs_journal *journal = SB_JOURNAL(sb); unsigned long bcount = journal->j_bcount; while (1) { - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); journal->j_current_jl->j_state |= LIST_COMMIT_PENDING; while ((atomic_read(&journal->j_wcount) > 0 || atomic_read(&journal->j_jlock)) && @@ -3024,14 +3024,12 @@ struct reiserfs_transaction_handle *reiserfs_persistent_transaction(struct } return th; } - th = reiserfs_kmalloc(sizeof(struct reiserfs_transaction_handle), - GFP_NOFS, s); + th = kmalloc(sizeof(struct reiserfs_transaction_handle), GFP_NOFS); if (!th) return NULL; ret = journal_begin(th, s, nblocks); if (ret) { - reiserfs_kfree(th, sizeof(struct reiserfs_transaction_handle), - s); + kfree(th); return NULL; } @@ -3049,8 +3047,7 @@ int reiserfs_end_persistent_transaction(struct reiserfs_transaction_handle *th) ret = -EIO; if (th->t_refcount == 0) { SB_JOURNAL(s)->j_persistent_trans--; - reiserfs_kfree(th, sizeof(struct reiserfs_transaction_handle), - s); + kfree(th); } return ret; } @@ -3907,10 +3904,13 @@ static int do_journal_end(struct reiserfs_transaction_handle *th, flush = 1; } #ifdef REISERFS_PREALLOCATE - /* quota ops might need to nest, setup the journal_info pointer for them */ + /* quota ops might need to nest, setup the journal_info pointer for them + * and raise the refcount so that it is > 0. */ current->journal_info = th; + th->t_refcount++; reiserfs_discard_all_prealloc(th); /* it should not involve new blocks into * the transaction */ + th->t_refcount--; current->journal_info = th->t_handle_save; #endif