%patch
Index: linux.d/fs/reiserfs/bitmap.c
===================================================================
--- linux.d.orig/fs/reiserfs/bitmap.c   2003-12-03 19:25:22.000000000 -0500
+++ linux.d/fs/reiserfs/bitmap.c        2003-12-03 19:25:44.000000000 -0500
@@ -296,7 +296,6 @@
    int nr, offset;

    PROC_INFO_INC( s, free_block );
-
    rs = SB_DISK_SUPER_BLOCK (s);
    sbh = SB_BUFFER_WITH_SB (s);
    apbi = SB_AP_BITMAP(s);
@@ -309,7 +308,6 @@
                         block, bdevname(s->s_dev));
       return;
    }
-
    reiserfs_prepare_for_journal(s, apbi[nr].bh, 1 ) ;

    /* clear bit for the given block in bit map */
@@ -599,7 +597,6 @@
    if (hint->formatted_node || hint->inode == NULL) {
       return 0;
    }
-
    hash_in = le32_to_cpu((INODE_PKEY(hint->inode))->k_dir_id);
    border = hint->beg + (unsigned long) keyed_hash(((char *) (&hash_in)), 4) % (hint->end - hint->beg - 1);
    if (border > hint->search_start)
Index: linux.d/fs/reiserfs/journal.c
===================================================================
--- linux.d.orig/fs/reiserfs/journal.c  2003-12-03 19:07:52.000000000 -0500
+++ linux.d/fs/reiserfs/journal.c       2003-12-03 19:30:33.000000000 -0500
@@ -64,12 +64,15 @@
*/
static int reiserfs_mounted_fs_count = 0 ;

+static struct list_head kreiserfsd_supers = LIST_HEAD_INIT(kreiserfsd_supers);
+
/* wake this up when you add something to the commit thread task queue */
DECLARE_WAIT_QUEUE_HEAD(reiserfs_commit_thread_wait) ;

/* wait on this if you need to be sure you task queue entries have been run */
static DECLARE_WAIT_QUEUE_HEAD(reiserfs_commit_thread_done) ;
DECLARE_TASK_QUEUE(reiserfs_commit_thread_tq) ;
+DECLARE_MUTEX(kreiserfsd_sem) ;

#define JOURNAL_TRANS_HALF 1018   /* must be correct to keep the desc and commit
                                    structs at 4k */
@@ -574,17 +577,12 @@
/* lock the current transaction */
inline static void lock_journal(struct super_block *p_s_sb) {
  PROC_INFO_INC( p_s_sb, journal.lock_journal );
-  while(atomic_read(&(SB_JOURNAL(p_s_sb)->j_wlock)) > 0) {
-    PROC_INFO_INC( p_s_sb, journal.lock_journal_wait );
-    sleep_on(&(SB_JOURNAL(p_s_sb)->j_wait)) ;
-  }
-  atomic_set(&(SB_JOURNAL(p_s_sb)->j_wlock), 1) ;
+  down(&SB_JOURNAL(p_s_sb)->j_lock);
}

/* unlock the current transaction */
inline static void unlock_journal(struct super_block *p_s_sb) {
-  atomic_dec(&(SB_JOURNAL(p_s_sb)->j_wlock)) ;
-  wake_up(&(SB_JOURNAL(p_s_sb)->j_wait)) ;
+  up(&SB_JOURNAL(p_s_sb)->j_lock);
}

/*
@@ -754,7 +752,6 @@
  atomic_set(&(jl->j_commit_flushing), 0) ;
  wake_up(&(jl->j_commit_wait)) ;

-  s->s_dirt = 1 ;
  return 0 ;
}

@@ -1218,7 +1215,6 @@
    if (run++ == 0) {
        goto loop_start ;
    }
-
    atomic_set(&(jl->j_flushing), 0) ;
    wake_up(&(jl->j_flush_wait)) ;
    return ret ;
@@ -1248,7 +1244,7 @@
    while(i != start) {
        jl = SB_JOURNAL_LIST(s) + i  ;
        age = CURRENT_TIME - jl->j_timestamp ;
-        if (jl->j_len > 0 && // age >= (JOURNAL_MAX_COMMIT_AGE * 2) &&
+        if (jl->j_len > 0 && age >= JOURNAL_MAX_COMMIT_AGE &&
            atomic_read(&(jl->j_nonzerolen)) > 0 &&
            atomic_read(&(jl->j_commit_left)) == 0) {

@@ -1327,6 +1323,10 @@
static int do_journal_release(struct reiserfs_transaction_handle *th, struct super_block *p_s_sb, int error) {
  struct reiserfs_transaction_handle myth ;

+  down(&kreiserfsd_sem);
+  list_del(&p_s_sb->u.reiserfs_sb.s_reiserfs_supers);
+  up(&kreiserfsd_sem);
+
  /* we only want to flush out transactions if we were called with error == 0
  */
  if (!error && !(p_s_sb->s_flags & MS_RDONLY)) {
@@ -1831,11 +1831,6 @@
  jl = SB_JOURNAL_LIST(ct->p_s_sb) + ct->jindex ;

  flush_commit_list(ct->p_s_sb, SB_JOURNAL_LIST(ct->p_s_sb) + ct->jindex, 1) ;
-
-  if (jl->j_len > 0 && atomic_read(&(jl->j_nonzerolen)) > 0 &&
-      atomic_read(&(jl->j_commit_left)) == 0) {
-    kupdate_one_transaction(ct->p_s_sb, jl) ;
-  }
  reiserfs_kfree(ct->self, sizeof(struct reiserfs_journal_commit_task), ct->p_s_sb) ;
}

@@ -1885,6 +1880,9 @@
** then run the per filesystem commit task queue when we wakeup.
*/
static int reiserfs_journal_commit_thread(void *nullp) {
+  struct list_head *entry, *safe ;
+  struct super_block *s;
+  time_t last_run = 0;

  daemonize() ;

@@ -1900,6 +1898,18 @@
    while(TQ_ACTIVE(reiserfs_commit_thread_tq)) {
      run_task_queue(&reiserfs_commit_thread_tq) ;
    }
+    if (CURRENT_TIME - last_run > 5) {
+       down(&kreiserfsd_sem);
+       list_for_each_safe(entry, safe, &kreiserfsd_supers) {
+           s = list_entry(entry, struct super_block,
+                          u.reiserfs_sb.s_reiserfs_supers);
+           if (!(s->s_flags & MS_RDONLY)) {
+               reiserfs_flush_old_commits(s);
+           }
+       }
+       up(&kreiserfsd_sem);
+       last_run = CURRENT_TIME;
+    }

    /* if there aren't any more filesystems left, break */
    if (reiserfs_mounted_fs_count <= 0) {
@@ -2054,7 +2064,6 @@
       reiserfs_warning(p_s_sb, "Journal size %d is less than 512+1 blocks, which unsupported\n", SB_ONDISK_JOURNAL_SIZE(p_s_sb));
       return 1 ;
    }
-
    journal = SB_JOURNAL(p_s_sb) = vmalloc(sizeof (struct reiserfs_journal)) ;
    if (!journal) {
       reiserfs_warning(p_s_sb, "journal-1256: unable to get memory for journal structure\n") ;
@@ -2182,13 +2191,12 @@
    SB_JOURNAL(p_s_sb)->j_last = NULL ;
    SB_JOURNAL(p_s_sb)->j_first = NULL ;
    init_waitqueue_head(&(SB_JOURNAL(p_s_sb)->j_join_wait)) ;
-    init_waitqueue_head(&(SB_JOURNAL(p_s_sb)->j_wait)) ;
-
+    sema_init(&SB_JOURNAL(p_s_sb)->j_lock, 1);
+
    SB_JOURNAL(p_s_sb)->j_trans_id = 10 ;
    SB_JOURNAL(p_s_sb)->j_mount_id = 10 ;
    SB_JOURNAL(p_s_sb)->j_state = 0 ;
    atomic_set(&(SB_JOURNAL(p_s_sb)->j_jlock), 0) ;
-    atomic_set(&(SB_JOURNAL(p_s_sb)->j_wlock), 0) ;
    SB_JOURNAL(p_s_sb)->j_cnode_free_list = allocate_cnodes(num_cnodes) ;
    SB_JOURNAL(p_s_sb)->j_cnode_free_orig = SB_JOURNAL(p_s_sb)->j_cnode_free_list ;
    SB_JOURNAL(p_s_sb)->j_cnode_free = SB_JOURNAL(p_s_sb)->j_cnode_free_list ?
@@ -2216,6 +2224,9 @@
       kernel_thread((void *)(void *)reiserfs_journal_commit_thread, NULL,
                     CLONE_FS | CLONE_FILES | CLONE_VM) ;
    }
+    down(&kreiserfsd_sem);
+    list_add(&p_s_sb->u.reiserfs_sb.s_reiserfs_supers, &kreiserfsd_supers);
+    up(&kreiserfsd_sem);
    return 0 ;

free_and_return:
@@ -2347,7 +2358,6 @@
  th->t_trans_id = SB_JOURNAL(p_s_sb)->j_trans_id ;
  th->t_caller = "Unknown" ;
  unlock_journal(p_s_sb) ;
-  p_s_sb->s_dirt = 1;
  return 0 ;
}

@@ -2389,7 +2399,7 @@
    reiserfs_panic(th->t_super, "journal-1577: handle trans id %ld != current trans id %ld\n",
                   th->t_trans_id, SB_JOURNAL(p_s_sb)->j_trans_id);
  }
-  p_s_sb->s_dirt = 1 ;
+  p_s_sb->s_dirt = 1;

  prepared = test_and_clear_bit(BH_JPrepared, &bh->b_state) ;
  /* already in this transaction, we are done */
@@ -2637,12 +2647,8 @@
** flushes any old transactions to disk
** ends the current transaction if it is too old
**
-** also calls flush_journal_list with old_only == 1, which allows me to reclaim
-** memory and such from the journal lists whose real blocks are all on disk.
-**
-** called by sync_dev_journal from buffer.c
*/
-int flush_old_commits(struct super_block *p_s_sb, int immediate) {
+int reiserfs_flush_old_commits(struct super_block *p_s_sb) {
  int i ;
  int count = 0;
  int start ;
@@ -2659,8 +2665,7 @@
  /* starting with oldest, loop until we get to the start */
  i = (SB_JOURNAL_LIST_INDEX(p_s_sb) + 1) % JOURNAL_LIST_COUNT ;
  while(i != start) {
-    if (SB_JOURNAL_LIST(p_s_sb)[i].j_len > 0 && ((now - SB_JOURNAL_LIST(p_s_sb)[i].j_timestamp) > SB_JOURNAL_MAX_COMMIT_AGE(p_s_sb) ||
-       immediate)) {
+    if (SB_JOURNAL_LIST(p_s_sb)[i].j_len > 0 && ((now - SB_JOURNAL_LIST(p_s_sb)[i].j_timestamp) > SB_JOURNAL_MAX_COMMIT_AGE(p_s_sb))) {
      /* we have to check again to be sure the current transaction did not change */
      if (i != SB_JOURNAL_LIST_INDEX(p_s_sb))  {
       flush_commit_list(p_s_sb, SB_JOURNAL_LIST(p_s_sb) + i, 1) ;
@@ -2669,26 +2674,26 @@
    i = (i + 1) % JOURNAL_LIST_COUNT ;
    count++ ;
  }
+
  /* now, check the current transaction.  If there are no writers, and it is too old, finish it, and
  ** force the commit blocks to disk
  */
-  if (!immediate && atomic_read(&(SB_JOURNAL(p_s_sb)->j_wcount)) <= 0 &&
+  if (atomic_read(&(SB_JOURNAL(p_s_sb)->j_wcount)) <= 0 &&
     SB_JOURNAL(p_s_sb)->j_trans_start_time > 0 &&
     SB_JOURNAL(p_s_sb)->j_len > 0 &&
     (now - SB_JOURNAL(p_s_sb)->j_trans_start_time) > SB_JOURNAL_MAX_TRANS_AGE(p_s_sb)) {
    journal_join(&th, p_s_sb, 1) ;
    reiserfs_prepare_for_journal(p_s_sb, SB_BUFFER_WITH_SB(p_s_sb), 1) ;
    journal_mark_dirty(&th, p_s_sb, SB_BUFFER_WITH_SB(p_s_sb)) ;
-    do_journal_end(&th, p_s_sb,1, COMMIT_NOW) ;
-  } else if (immediate) { /* belongs above, but I wanted this to be very explicit as a special case.  If they say to
-                             flush, we must be sure old transactions hit the disk too. */
-    journal_join(&th, p_s_sb, 1) ;
-    reiserfs_prepare_for_journal(p_s_sb, SB_BUFFER_WITH_SB(p_s_sb), 1) ;
-    journal_mark_dirty(&th, p_s_sb, SB_BUFFER_WITH_SB(p_s_sb)) ;
+
+    /* we're only being called from kreiserfsd, it makes no sense to do
+    ** an async commit so that kreiserfsd can do it later
+    */
    do_journal_end(&th, p_s_sb,1, COMMIT_NOW | WAIT) ;
-  }
-   reiserfs_journal_kupdate(p_s_sb) ;
-   return 0 ;
+  }
+  reiserfs_journal_kupdate(p_s_sb) ;
+
+  return p_s_sb->s_dirt;
}

/*
@@ -2727,7 +2732,7 @@
  if (SB_JOURNAL(p_s_sb)->j_len == 0) {
    int wcount = atomic_read(&(SB_JOURNAL(p_s_sb)->j_wcount)) ;
    unlock_journal(p_s_sb) ;
-    if (atomic_read(&(SB_JOURNAL(p_s_sb)->j_jlock))  > 0 && wcount <= 0) {
+    if (atomic_read(&(SB_JOURNAL(p_s_sb)->j_jlock)) > 0 && wcount <= 0) {
      atomic_dec(&(SB_JOURNAL(p_s_sb)->j_jlock)) ;
      wake_up(&(SB_JOURNAL(p_s_sb)->j_join_wait)) ;
    }
@@ -3017,6 +3022,7 @@
  ** it tells us if we should continue with the journal_end, or just return
  */
  if (!check_journal_end(th, p_s_sb, nblocks, flags)) {
+    p_s_sb->s_dirt = 1;
    return 0 ;
  }

@@ -3185,14 +3191,12 @@
  /* write any buffers that must hit disk before this commit is done */
  fsync_buffers_list(&(SB_JOURNAL(p_s_sb)->j_dirty_buffers)) ;

-  /* honor the flush and async wishes from the caller */
+  /* honor the flush wishes from the caller.  simple commits can
+   * be done outside the journal lock, they are done below
+   */
  if (flush) {
    flush_commit_list(p_s_sb, SB_JOURNAL_LIST(p_s_sb) + orig_jindex, 1) ;
    flush_journal_list(p_s_sb,  SB_JOURNAL_LIST(p_s_sb) + orig_jindex , 1) ;
-  } else if (wait_on_commit) {
-    flush_commit_list(p_s_sb, SB_JOURNAL_LIST(p_s_sb) + orig_jindex, 1) ;
-  } else {
-    commit_flush_async(p_s_sb, orig_jindex) ;
  }

  /* reset journal values for the next transaction */
@@ -3254,5 +3258,15 @@
  atomic_set(&(SB_JOURNAL(p_s_sb)->j_jlock), 0) ;
  /* wake up any body waiting to join. */
  wake_up(&(SB_JOURNAL(p_s_sb)->j_join_wait)) ;
+
+  if (!flush) {
+    if (current->need_resched)
+      schedule() ;
+    if (wait_on_commit) {
+      flush_commit_list(p_s_sb, SB_JOURNAL_LIST(p_s_sb) + orig_jindex, 1) ;
+    } else {
+      commit_flush_async(p_s_sb, orig_jindex) ;
+    }
+  }
  return 0 ;
}
Index: linux.d/fs/reiserfs/objectid.c
===================================================================
--- linux.d.orig/fs/reiserfs/objectid.c 2003-12-03 19:25:22.000000000 -0500
+++ linux.d/fs/reiserfs/objectid.c      2003-12-03 19:25:44.000000000 -0500
@@ -87,7 +87,6 @@
    }

    journal_mark_dirty(th, s, SB_BUFFER_WITH_SB (s));
-    s->s_dirt = 1;
    return unused_objectid;
}

@@ -106,8 +105,6 @@

    reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1) ;
    journal_mark_dirty(th, s, SB_BUFFER_WITH_SB (s));
-    s->s_dirt = 1;
-

    /* start at the beginning of the objectid map (i = 0) and go to
       the end of it (i = disk_sb->s_oid_cursize).  Linear search is
Index: linux.d/fs/reiserfs/super.c
===================================================================
--- linux.d.orig/fs/reiserfs/super.c    2003-12-03 19:25:22.000000000 -0500
+++ linux.d/fs/reiserfs/super.c 2003-12-03 19:25:44.000000000 -0500
@@ -50,22 +50,28 @@
static int reiserfs_remount (struct super_block * s, int * flags, char * data);
static int reiserfs_statfs (struct super_block * s, struct statfs * buf);

-static void reiserfs_write_super (struct super_block * s)
+static int reiserfs_sync_fs (struct super_block * s)
{
+    struct reiserfs_transaction_handle th;
+    lock_kernel() ;
+    if (!(s->s_flags & MS_RDONLY)) {
+       journal_begin(&th, s, 1);
+       journal_end_sync(&th, s, 1);
+       s->s_dirt = 0;
+    }
+    unlock_kernel() ;
+    return 0;
+}

-  int dirty = 0 ;
-  lock_kernel() ;
-  if (!(s->s_flags & MS_RDONLY)) {
-    dirty = flush_old_commits(s, 1) ;
-  }
-  s->s_dirt = dirty;
-  unlock_kernel() ;
+static void reiserfs_write_super (struct super_block * s)
+{
+    reiserfs_sync_fs(s);
}

+
static void reiserfs_write_super_lockfs (struct super_block * s)
{

-  int dirty = 0 ;
  struct reiserfs_transaction_handle th ;
  lock_kernel() ;
  if (!(s->s_flags & MS_RDONLY)) {
@@ -75,7 +81,7 @@
    reiserfs_block_writes(&th) ;
    journal_end(&th, s, 1) ;
  }
-  s->s_dirt = dirty;
+  s->s_dirt = 0;
  unlock_kernel() ;
}

@@ -357,6 +363,7 @@
  ** to do a journal_end
  */
  journal_release(&th, s) ;
+  s->s_dirt = 0;

  for (i = 0; i < SB_BMAP_NR (s); i ++)
    brelse (SB_AP_BITMAP (s)[i].bh);
@@ -418,6 +425,7 @@
  put_super: reiserfs_put_super,
  write_super: reiserfs_write_super,
  write_super_lockfs: reiserfs_write_super_lockfs,
+  sync_fs: reiserfs_sync_fs,
  unlockfs: reiserfs_unlockfs,
  statfs: reiserfs_statfs,
  remount_fs: reiserfs_remount,
@@ -1172,9 +1180,6 @@

    if (reiserfs_parse_options (s, (char *) data, &(s->u.reiserfs_sb.s_mount_opt), &blocks) == 0) {
      return NULL;
-
-
-
    }

    if (blocks) {
Index: linux.d/fs/reiserfs/ibalance.c
===================================================================
--- linux.d.orig/fs/reiserfs/ibalance.c 2003-12-03 19:25:22.000000000 -0500
+++ linux.d/fs/reiserfs/ibalance.c      2003-12-03 19:25:44.000000000 -0500
@@ -632,7 +632,6 @@
               /* use check_internal if new root is an internal node */
               check_internal (new_root);
           /*&&&&&&&&&&&&&&&&&&&&&&*/
-           tb->tb_sb->s_dirt = 1;

           /* do what is needed for buffer thrown from tree */
           reiserfs_invalidate_buffer(tb, tbSh);
@@ -950,7 +949,6 @@
        PUT_SB_ROOT_BLOCK( tb->tb_sb, tbSh->b_blocknr );
        PUT_SB_TREE_HEIGHT( tb->tb_sb, SB_TREE_HEIGHT(tb->tb_sb) + 1 );
       do_balance_mark_sb_dirty (tb, tb->tb_sb->u.reiserfs_sb.s_sbh, 1);
-       tb->tb_sb->s_dirt = 1;
    }

    if ( tb->blknum[h] == 2 ) {
Index: linux.d/include/linux/reiserfs_fs_sb.h
===================================================================
--- linux.d.orig/include/linux/reiserfs_fs_sb.h 2003-12-03 19:25:22.000000000 -0500
+++ linux.d/include/linux/reiserfs_fs_sb.h      2003-12-03 19:25:44.000000000 -0500
@@ -235,8 +235,7 @@
  */
  struct reiserfs_page_list *j_flush_pages ;
  time_t j_trans_start_time ;         /* time this transaction started */
-  wait_queue_head_t j_wait ;         /* wait  journal_end to finish I/O */
-  atomic_t j_wlock ;                       /* lock for j_wait */
+  struct semaphore j_lock ;
  wait_queue_head_t j_join_wait ;    /* wait for current transaction to finish before starting new one */
  atomic_t j_jlock ;                       /* lock for j_join_wait */
  int j_journal_list_index ;         /* journal list number of the current trans */
@@ -413,6 +412,7 @@
    reiserfs_proc_info_data_t s_proc_info_data;
    struct proc_dir_entry *procdir;
    int reserved_blocks; /* amount of blocks reserved for further allocations */
+    struct list_head s_reiserfs_supers;
};

/* Definitions of reiserfs on-disk properties: */
@@ -481,7 +481,6 @@
void reiserfs_file_buffer (struct buffer_head * bh, int list);
int reiserfs_is_super(struct super_block *s)  ;
int journal_mark_dirty(struct reiserfs_transaction_handle *, struct super_block *, struct buffer_head *bh) ;
-int flush_old_commits(struct super_block *s, int) ;
int show_reiserfs_locks(void) ;
int reiserfs_resize(struct super_block *, unsigned long) ;

Index: linux.d/include/linux/reiserfs_fs.h
===================================================================
--- linux.d.orig/include/linux/reiserfs_fs.h    2003-12-03 19:25:22.000000000 -0500
+++ linux.d/include/linux/reiserfs_fs.h 2003-12-03 19:25:44.000000000 -0500
@@ -1693,6 +1693,7 @@
*/
#define JOURNAL_BUFFER(j,n) ((j)->j_ap_blocks[((j)->j_start + (n)) % JOURNAL_BLOCK_COUNT])

+int reiserfs_flush_old_commits(struct super_block *);
void reiserfs_commit_for_inode(struct inode *) ;
void reiserfs_commit_for_tail(struct inode *) ;
void reiserfs_update_inode_transaction(struct inode *) ;