From 57aa463be36546db8a78bf391fb94e1f1066141f Mon Sep 17 00:00:00 2001 From: adilger Date: Sun, 16 Nov 2003 22:55:54 +0000 Subject: [PATCH] Add journal callback patch for SuSE 2.4.19 ia64 kernel (in vanilla 2.4.20). --- .../kernel_patches/patches/jbd-2.4.18-jcberr.patch | 262 +++++++++++++++++++++ 1 file changed, 262 insertions(+) create mode 100644 lustre/kernel_patches/patches/jbd-2.4.18-jcberr.patch 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 index 0000000..aa522c6 --- /dev/null +++ b/lustre/kernel_patches/patches/jbd-2.4.18-jcberr.patch @@ -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 -- 1.8.3.1