--- /dev/null
+
+--- linux-2.4.18/fs/jbd/checkpoint.c~jbd-commit-tricks Mon Jul 28 13:52:05 2003
++++ linux-2.4.18-alexey/fs/jbd/checkpoint.c Mon Jul 28 14:03:59 2003
+@@ -77,19 +77,23 @@ static int __try_to_free_cp_buf(struct j
+ * to wait for a checkpoint to free up some space in the log.
+ */
+
+-void log_wait_for_space(journal_t *journal, int nblocks)
++void log_wait_for_space(journal_t *journal)
+ {
++ int nblocks;
++
++ nblocks = jbd_space_needed(journal);
+ while (log_space_left(journal) < nblocks) {
+ if (journal->j_flags & JFS_ABORT)
+ return;
+ unlock_journal(journal);
+ down(&journal->j_checkpoint_sem);
+ lock_journal(journal);
++ nblocks = jbd_space_needed(journal);
+
+ /* Test again, another process may have checkpointed
+ * while we were waiting for the checkpoint lock */
+ if (log_space_left(journal) < nblocks) {
+- log_do_checkpoint(journal, nblocks);
++ log_do_checkpoint(journal);
+ }
+ up(&journal->j_checkpoint_sem);
+ }
+@@ -260,8 +264,7 @@ static int __flush_buffer(journal_t *jou
+ * The journal should be locked before calling this function.
+ */
+
+-/* @@@ `nblocks' is unused. Should it be used? */
+-int log_do_checkpoint (journal_t *journal, int nblocks)
++int log_do_checkpoint (journal_t *journal)
+ {
+ transaction_t *transaction, *last_transaction, *next_transaction;
+ int result;
+@@ -315,6 +318,8 @@ repeat:
+ retry = __flush_buffer(journal, jh, bhs, &batch_count,
+ &drop_count);
+ } while (jh != last_jh && !retry);
++ if (journal->j_checkpoint_transactions != transaction)
++ goto done;
+ if (batch_count) {
+ __flush_batch(bhs, &batch_count);
+ goto repeat;
+@@ -328,6 +333,8 @@ repeat:
+ */
+ cleanup_ret = __cleanup_transaction(journal, transaction);
+ J_ASSERT(drop_count != 0 || cleanup_ret != 0);
++ if (journal->j_checkpoint_transactions != transaction)
++ goto done;
+ goto repeat; /* __cleanup may have dropped lock */
+ } while (transaction != last_transaction);
+
+--- linux-2.4.18/fs/jbd/journal.c~jbd-commit-tricks Mon Jul 28 13:52:05 2003
++++ linux-2.4.18-alexey/fs/jbd/journal.c Mon Jul 28 14:03:59 2003
+@@ -1115,7 +1115,7 @@ void journal_destroy (journal_t *journal
+ /* Force any old transactions to disk */
+ lock_journal(journal);
+ while (journal->j_checkpoint_transactions != NULL)
+- log_do_checkpoint(journal, 1);
++ log_do_checkpoint(journal);
+
+ J_ASSERT(journal->j_running_transaction == NULL);
+ J_ASSERT(journal->j_committing_transaction == NULL);
+@@ -1302,7 +1302,7 @@ int journal_flush (journal_t *journal)
+ /* ...and flush everything in the log out to disk. */
+ lock_journal(journal);
+ while (!err && journal->j_checkpoint_transactions != NULL)
+- err = log_do_checkpoint(journal, journal->j_maxlen);
++ err = log_do_checkpoint(journal);
+ cleanup_journal_tail(journal);
+
+ /* Finally, mark the journal as really needing no recovery.
+--- linux-2.4.18/fs/jbd/transaction.c~jbd-commit-tricks Mon Jul 28 13:52:05 2003
++++ linux-2.4.18-alexey/fs/jbd/transaction.c Mon Jul 28 14:03:59 2003
+@@ -182,14 +182,9 @@ repeat_locked:
+ * Also, this test is inconsitent with the matching one in
+ * journal_extend().
+ */
+- needed = journal->j_max_transaction_buffers;
+- if (journal->j_committing_transaction)
+- needed += journal->j_committing_transaction->
+- t_outstanding_credits;
+-
+- if (log_space_left(journal) < needed) {
++ if (log_space_left(journal) < jbd_space_needed(journal)) {
+ jbd_debug(2, "Handle %p waiting for checkpoint...\n", handle);
+- log_wait_for_space(journal, needed);
++ log_wait_for_space(journal);
+ goto repeat_locked;
+ }
+
+--- linux-2.4.18/include/linux/jbd.h~jbd-commit-tricks Mon Jul 28 13:52:17 2003
++++ linux-2.4.18-alexey/include/linux/jbd.h Mon Jul 28 14:03:59 2003
+@@ -740,9 +740,9 @@ extern void journal_brelse_array(stru
+ extern int log_space_left (journal_t *); /* Called with journal locked */
+ extern tid_t log_start_commit (journal_t *, transaction_t *);
+ extern int log_wait_commit (journal_t *, tid_t);
+-extern int log_do_checkpoint (journal_t *, int);
++extern int log_do_checkpoint (journal_t *);
+
+-extern void log_wait_for_space(journal_t *, int nblocks);
++extern void log_wait_for_space(journal_t *);
+ extern void __journal_drop_transaction(journal_t *, transaction_t *);
+ extern int cleanup_journal_tail(journal_t *);
+
+@@ -815,6 +815,19 @@ static inline int tid_geq(tid_t x, tid_t
+ }
+
+ extern int journal_blocks_per_page(struct inode *inode);
++
++/*
++ * Return the minimum number of blocks which must be free in the journal
++ * before a new transaction may be started. Must be called under j_state_lock.
++ */
++static inline int jbd_space_needed(journal_t *journal)
++{
++ int nblocks = journal->j_max_transaction_buffers;
++ if (journal->j_committing_transaction)
++ nblocks += journal->j_committing_transaction->
++ t_outstanding_credits;
++ return nblocks;
++}
+
+ /*
+ * Definitions which augment the buffer_head layer
+
+_
===================================================================
--- linux-2.4.21-chaos.orig/fs/ext2/inode.c 2003-07-15 04:41:01.000000000 +0400
+++ linux-2.4.21-chaos/fs/ext2/inode.c 2003-12-14 15:11:46.000000000 +0300
-@@ -39,6 +39,18 @@
- static int ext2_update_inode(struct inode * inode, int do_sync);
-
- /*
-+ * Test whether an inode is a fast symlink.
-+ */
-+static inline int ext2_inode_is_fast_symlink(struct inode *inode)
-+{
-+ int ea_blocks = inode->u.ext2_i.i_file_acl ?
-+ (inode->i_sb->s_blocksize >> 9) : 0;
-+
-+ return (S_ISLNK(inode->i_mode) &&
-+ inode->i_blocks - ea_blocks == 0);
-+}
-+
-+/*
- * Called at each iput()
- */
- void ext2_put_inode (struct inode * inode)
@@ -53,9 +65,7 @@
{
lock_kernel();
inode->i_op = &ext2_file_inode_operations;
inode->i_fop = &ext2_file_operations;
inode->i_mapping->a_ops = &ext2_aops;
-@@ -1002,15 +1010,17 @@
- inode->i_fop = &ext2_dir_operations;
- inode->i_mapping->a_ops = &ext2_aops;
- } else if (S_ISLNK(inode->i_mode)) {
-- if (!inode->i_blocks)
-+ if (ext2_inode_is_fast_symlink(inode))
+@@ -1002,12 +1010,14 @@
+ if (ext2_inode_is_fast_symlink(inode))
inode->i_op = &ext2_fast_symlink_inode_operations;
else {
- inode->i_op = &page_symlink_inode_operations;