Whamcloud - gitweb
Add journal callback patch for SuSE 2.4.19 ia64 kernel (in vanilla 2.4.20).
authoradilger <adilger>
Sun, 16 Nov 2003 22:55:54 +0000 (22:55 +0000)
committeradilger <adilger>
Sun, 16 Nov 2003 22:55:54 +0000 (22:55 +0000)
lustre/kernel_patches/patches/jbd-2.4.18-jcberr.patch [new file with mode: 0644]

diff --git a/lustre/kernel_patches/patches/jbd-2.4.18-jcberr.patch b/lustre/kernel_patches/patches/jbd-2.4.18-jcberr.patch
new file mode 100644 (file)
index 0000000..aa522c6
--- /dev/null
@@ -0,0 +1,262 @@
+--- lum/include/linux/jbd.h.orig       Tue Apr 16 14:27:25 2002
++++ lum/include/linux/jbd.h    Wed Apr 24 05:19:00 2002
+@@ -249,6 +249,13 @@
+       return bh->b_private;
+ }
++#define HAVE_JOURNAL_CALLBACK_STATUS
++struct journal_callback {
++      struct list_head jcb_list;
++      void (*jcb_func)(struct journal_callback *jcb, int error);
++      /* user data goes here */
++};
++
+ struct jbd_revoke_table_s;
+ /* The handle_t type represents a single atomic update being performed
+@@ -279,6 +285,12 @@
+          operations */
+       int                     h_err;
++      /* List of application registered callbacks for this handle.
++       * The function(s) will be called after the transaction that
++       * this handle is part of has been committed to disk.
++       */
++      struct list_head        h_jcb;
++
+       /* Flags */
+       unsigned int    h_sync:         1;      /* sync-on-close */
+       unsigned int    h_jdata:        1;      /* force data journaling */
+@@ -398,6 +410,10 @@
+       /* How many handles used this transaction? */
+       int t_handle_count;
++
++      /* List of registered callback functions for this transaction.
++       * Called when the transaction is committed. */
++      struct list_head        t_jcb;
+ };
+@@ -646,6 +662,9 @@
+ extern int     journal_try_to_free_buffers(journal_t *, struct page *, int);
+ extern int     journal_stop(handle_t *);
+ extern int     journal_flush (journal_t *);
++extern void    journal_callback_set(handle_t *handle,
++                                    void (*fn)(struct journal_callback *,int),
++                                    struct journal_callback *jcb);
+ extern void    journal_lock_updates (journal_t *);
+ extern void    journal_unlock_updates (journal_t *);
+--- linux/fs/jbd/checkpoint.c.orig     Tue Feb 26 17:07:38 2002
++++ linux/fs/jbd/checkpoint.c  Thu May 16 13:35:44 2002
+@@ -594,7 +594,8 @@
+       J_ASSERT (transaction->t_log_list == NULL);
+       J_ASSERT (transaction->t_checkpoint_list == NULL);
+       J_ASSERT (transaction->t_updates == 0);
+-      
++      J_ASSERT (list_empty(&transaction->t_jcb));
++
+       J_ASSERT (transaction->t_journal->j_committing_transaction !=
+                                       transaction);
+       
+--- lum/fs/jbd/commit.c.orig   Tue Feb 26 17:07:38 2002
++++ lum/fs/jbd/commit.c        Thu May 16 13:54:39 2002
+@@ -47,6 +47,7 @@
+       struct buffer_head *wbuf[64];
+       int bufs;
+       int flags;
++      int unlocked;
+       int err;
+       unsigned long blocknr;
+       char *tagp = NULL;
+@@ -475,7 +476,7 @@
+            transaction's t_log_list queue, and metadata buffers are on
+            the t_iobuf_list queue.
+-         Wait for the transactions in reverse order.  That way we are
++         Wait for the buffers in reverse order.  That way we are
+          less likely to be woken up until all IOs have completed, and
+          so we incur less scheduling load.
+       */
+@@ -566,6 +567,7 @@
+       jbd_debug(3, "JBD: commit phase 6\n");
++      unlocked = 0;
+       if (is_journal_aborted(journal))
+               goto skip_commit;
+@@ -579,7 +581,7 @@
+               __journal_abort_hard(journal);
+               goto skip_commit;
+       }
+-      
++
+       /* AKPM: buglet - add `i' to tmp! */
+       for (i = 0; i < jh2bh(descriptor)->b_size; i += 512) {
+               journal_header_t *tmp =
+@@ -590,6 +592,7 @@
+       }
+       unlock_journal(journal);
++      unlocked = 1;
+       JBUFFER_TRACE(descriptor, "write commit block");
+       {
+               struct buffer_head *bh = jh2bh(descriptor);
+@@ -600,7 +603,6 @@
+               put_bh(bh);             /* One for getblk() */
+               journal_unlock_journal_head(descriptor);
+       }
+-      lock_journal(journal);
+       /* End of a transaction!  Finally, we can do checkpoint
+            processing: any buffers committed as a result of this
+@@ -609,6 +611,31 @@
+ skip_commit:
++      /* Call any callbacks that had been registered for handles in this
++       * transaction.  It is up to the callback to free any allocated
++       * memory.
++       */
++      if (!list_empty(&commit_transaction->t_jcb)) {
++              struct list_head *p, *n;
++              int error = is_journal_aborted(journal);
++
++              if (!unlocked) {
++                      unlock_journal(journal);
++                      unlocked = 1;
++              }
++
++              list_for_each_safe(p, n, &commit_transaction->t_jcb) {
++                      struct journal_callback *jcb;
++
++                      jcb = list_entry(p, struct journal_callback, jcb_list);
++                      list_del(p);
++                      jcb->jcb_func(jcb, error);
++              }
++      }
++
++      if (unlocked)
++              lock_journal(journal);
++
+       jbd_debug(3, "JBD: commit phase 7\n");
+       J_ASSERT(commit_transaction->t_sync_datalist == NULL);
+--- lum/fs/jbd/journal.c.orig  Fri Apr 12 10:27:52 2002
++++ lum/fs/jbd/journal.c       Wed Apr 24 05:18:49 2002
+@@ -58,6 +58,7 @@
+ #endif
+ EXPORT_SYMBOL(journal_flush);
+ EXPORT_SYMBOL(journal_revoke);
++EXPORT_SYMBOL(journal_callback_set);
+ EXPORT_SYMBOL(journal_init_dev);
+ EXPORT_SYMBOL(journal_init_inode);
+--- lum/fs/jbd/transaction.c.orig      Fri Apr 12 10:27:52 2002
++++ lum/fs/jbd/transaction.c   Wed Apr 24 05:31:14 2002
+@@ -57,6 +57,7 @@
+       transaction->t_state = T_RUNNING;
+       transaction->t_tid = journal->j_transaction_sequence++;
+       transaction->t_expires = jiffies + journal->j_commit_interval;
++      INIT_LIST_HEAD(&transaction->t_jcb);
+       /* Set up the commit timer for the new transaction. */
+       J_ASSERT (!journal->j_commit_timer_active);
+@@ -201,6 +202,20 @@
+       return 0;
+ }
++/* Allocate a new handle.  This should probably be in a slab... */
++static handle_t *new_handle(int nblocks)
++{
++      handle_t *handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS);
++      if (!handle)
++              return NULL;
++      memset(handle, 0, sizeof (handle_t));
++      handle->h_buffer_credits = nblocks;
++      handle->h_ref = 1;
++      INIT_LIST_HEAD(&handle->h_jcb);
++
++      return handle;
++}
++
+ /*
+  * Obtain a new handle.  
+  *
+@@ -227,14 +242,11 @@
+               handle->h_ref++;
+               return handle;
+       }
+-      
+-      handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS);
++
++      handle = new_handle(nblocks);
+       if (!handle)
+               return ERR_PTR(-ENOMEM);
+-      memset (handle, 0, sizeof (handle_t));
+-      handle->h_buffer_credits = nblocks;
+-      handle->h_ref = 1;
+       current->journal_info = handle;
+       err = start_this_handle(journal, handle);
+@@ -333,14 +345,11 @@
+       
+       if (is_journal_aborted(journal))
+               return ERR_PTR(-EIO);
+-      
+-      handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS);
++
++      handle = new_handle(nblocks);
+       if (!handle)
+               return ERR_PTR(-ENOMEM);
+-      memset (handle, 0, sizeof (handle_t));
+-      handle->h_buffer_credits = nblocks;
+-      handle->h_ref = 1;
+       current->journal_info = handle;
+       err = try_start_this_handle(journal, handle);
+@@ -1328,6 +1337,28 @@
+ #endif
+ /*
++ * Register a callback function for this handle.  The function will be
++ * called when the transaction that this handle is part of has been
++ * committed to disk with the original callback data struct and the
++ * error status of the journal as parameters.  There is no guarantee of
++ * ordering between handles within a single transaction, nor between
++ * callbacks registered on the same handle.
++ *
++ * The caller is responsible for allocating the journal_callback struct.
++ * This is to allow the caller to add as much extra data to the callback
++ * as needed, but reduce the overhead of multiple allocations.  The caller
++ * allocated struct must start with a struct journal_callback at offset 0,
++ * and has the caller-specific data afterwards.
++ */
++void journal_callback_set(handle_t *handle,
++                        void (*func)(struct journal_callback *jcb, int error),
++                        struct journal_callback *jcb)
++{
++      list_add_tail(&jcb->jcb_list, &handle->h_jcb);
++      jcb->jcb_func = func;
++}
++
++/*
+  * All done for a particular handle.
+  *
+  * There is not much action needed here.  We just return any remaining
+@@ -1393,7 +1423,10 @@
+                       wake_up(&journal->j_wait_transaction_locked);
+       }
+-      /* 
++      /* Move callbacks from the handle to the transaction. */
++      list_splice(&handle->h_jcb, &transaction->t_jcb);
++
++      /*
+        * If the handle is marked SYNC, we need to set another commit
+        * going!  We also want to force a commit if the current
+        * transaction is occupying too much of the log, or if the