diff -urN linux-2.4.27-wt2-reiserfs-01/fs/reiserfs/journal.c linux-2.4.27-wt2-reiserfs-01-fix/fs/reiserfs/journal.c --- linux-2.4.27-wt2-reiserfs-01/fs/reiserfs/journal.c Mon Aug 16 11:10:45 2004 +++ linux-2.4.27-wt2-reiserfs-01-fix/fs/reiserfs/journal.c Mon Aug 16 11:13:58 2004 @@ -2367,12 +2367,48 @@ static int journal_join(struct reiserfs_transaction_handle *th, struct super_block *p_s_sb, unsigned long nblocks) { + struct reiserfs_transaction_handle *cur_th = current->journal_info; + + /* this keeps do_journal_end from NULLing out the current->journal_info + ** pointer + */ + th->t_handle_save = cur_th ; + if (cur_th && cur_th->t_refcount > 1) { + BUG() ; + } return do_journal_begin_r(th, p_s_sb, nblocks, 1) ; } int journal_begin(struct reiserfs_transaction_handle *th, struct super_block * p_s_sb, unsigned long nblocks) { - conditional_schedule(); - return do_journal_begin_r(th, p_s_sb, nblocks, 0) ; + struct reiserfs_transaction_handle *cur_th = current->journal_info ; + int ret ; + + th->t_handle_save = NULL ; + if (cur_th) { + /* we are nesting into the current transaction */ + if (cur_th->t_super == p_s_sb) { + cur_th->t_refcount++ ; + memcpy(th, cur_th, sizeof(*th)); + if (th->t_refcount <= 1) + printk("BAD: refcount <= 1, but journal_info != 0\n"); + return 0; + } else { + /* we've ended up with a handle from a different filesystem. + ** save it and restore on journal_end. This should never + ** really happen... + */ + reiserfs_warning(p_s_sb, "clm-2100: nesting info a different FS\n") ; + th->t_handle_save = current->journal_info ; + current->journal_info = th; + } + } else { + current->journal_info = th; + } + conditional_schedule(); + ret = do_journal_begin_r(th, p_s_sb, nblocks, 0) ; + if (current->journal_info != th) + BUG() ; + return ret ; } /* not used at all */ @@ -2512,8 +2548,24 @@ } int journal_end(struct reiserfs_transaction_handle *th, struct super_block *p_s_sb, unsigned long nblocks) { - conditional_schedule(); - return do_journal_end(th, p_s_sb, nblocks, 0) ; + if (!current->journal_info && th->t_refcount > 1) + printk("REISER-NESTING: th NULL, refcount %d\n", th->t_refcount); + if (th->t_refcount > 1) { + struct reiserfs_transaction_handle *cur_th = current->journal_info ; + + /* we aren't allowed to close a nested transaction on a different + ** filesystem from the one in the task struct + */ + if (cur_th->t_super != th->t_super) + BUG() ; + + th->t_refcount--; + memcpy(current->journal_info, th, sizeof(*th)); + return 0; + } else { + conditional_schedule(); + return do_journal_end(th, p_s_sb, nblocks, 0) ; + } } /* removes from the current transaction, relsing and descrementing any counters.