4 fs/jbd/commit.c | 27 +++++++++++++++++++++---
6 fs/jbd/transaction.c | 56 ++++++++++++++++++++++++++++++++++++++++-----------
7 include/linux/jbd.h | 20 ++++++++++++++++++
8 4 files changed, 90 insertions(+), 14 deletions(-)
10 --- linux-2.4.19/fs/jbd/commit.c~vanilla-2.4.19 Sun Jan 19 19:46:42 2003
11 +++ linux-2.4.19-root/fs/jbd/commit.c Sun Jan 19 19:46:42 2003
12 @@ -475,7 +475,7 @@ start_journal_io:
13 transaction's t_log_list queue, and metadata buffers are on
14 the t_iobuf_list queue.
16 - Wait for the transactions in reverse order. That way we are
17 + Wait for the buffers in reverse order. That way we are
18 less likely to be woken up until all IOs have completed, and
19 so we incur less scheduling load.
21 @@ -566,8 +566,10 @@ start_journal_io:
23 jbd_debug(3, "JBD: commit phase 6\n");
25 - if (is_journal_aborted(journal))
26 + if (is_journal_aborted(journal)) {
27 + unlock_journal(journal);
31 /* Done it all: now write the commit record. We should have
32 * cleaned up our previous buffers by now, so if we are in abort
33 @@ -577,6 +579,7 @@ start_journal_io:
34 descriptor = journal_get_descriptor_buffer(journal);
36 __journal_abort_hard(journal);
37 + unlock_journal(journal);
41 @@ -600,7 +603,6 @@ start_journal_io:
42 put_bh(bh); /* One for getblk() */
43 journal_unlock_journal_head(descriptor);
45 - lock_journal(journal);
47 /* End of a transaction! Finally, we can do checkpoint
48 processing: any buffers committed as a result of this
49 @@ -609,6 +611,25 @@ start_journal_io:
53 + /* Call any callbacks that had been registered for handles in this
54 + * transaction. It is up to the callback to free any allocated
57 + if (!list_empty(&commit_transaction->t_jcb)) {
58 + struct list_head *p, *n;
59 + int error = is_journal_aborted(journal);
61 + list_for_each_safe(p, n, &commit_transaction->t_jcb) {
62 + struct journal_callback *jcb;
64 + jcb = list_entry(p, struct journal_callback, jcb_list);
66 + jcb->jcb_func(jcb, error);
70 + lock_journal(journal);
72 jbd_debug(3, "JBD: commit phase 7\n");
74 J_ASSERT(commit_transaction->t_sync_datalist == NULL);
75 --- linux-2.4.19/fs/jbd/journal.c~vanilla-2.4.19 Sun Jan 19 19:46:42 2003
76 +++ linux-2.4.19-root/fs/jbd/journal.c Sun Jan 19 19:46:42 2003
77 @@ -58,6 +58,7 @@ EXPORT_SYMBOL(journal_sync_buffer);
79 EXPORT_SYMBOL(journal_flush);
80 EXPORT_SYMBOL(journal_revoke);
81 +EXPORT_SYMBOL(journal_callback_set);
83 EXPORT_SYMBOL(journal_init_dev);
84 EXPORT_SYMBOL(journal_init_inode);
85 --- linux-2.4.19/fs/jbd/transaction.c~vanilla-2.4.19 Sun Jan 19 19:46:42 2003
86 +++ linux-2.4.19-root/fs/jbd/transaction.c Sun Jan 19 19:46:42 2003
87 @@ -57,6 +57,7 @@ static transaction_t * get_transaction (
88 transaction->t_state = T_RUNNING;
89 transaction->t_tid = journal->j_transaction_sequence++;
90 transaction->t_expires = jiffies + journal->j_commit_interval;
91 + INIT_LIST_HEAD(&transaction->t_jcb);
93 /* Set up the commit timer for the new transaction. */
94 J_ASSERT (!journal->j_commit_timer_active);
95 @@ -201,6 +202,20 @@ repeat_locked:
99 +/* Allocate a new handle. This should probably be in a slab... */
100 +static handle_t *new_handle(int nblocks)
102 + handle_t *handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS);
105 + memset(handle, 0, sizeof (handle_t));
106 + handle->h_buffer_credits = nblocks;
108 + INIT_LIST_HEAD(&handle->h_jcb);
114 * Obtain a new handle.
116 @@ -227,14 +242,11 @@ handle_t *journal_start(journal_t *journ
121 - handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS);
123 + handle = new_handle(nblocks);
125 return ERR_PTR(-ENOMEM);
126 - memset (handle, 0, sizeof (handle_t));
128 - handle->h_buffer_credits = nblocks;
130 current->journal_info = handle;
132 err = start_this_handle(journal, handle);
133 @@ -333,14 +345,11 @@ handle_t *journal_try_start(journal_t *j
135 if (is_journal_aborted(journal))
136 return ERR_PTR(-EIO);
138 - handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS);
140 + handle = new_handle(nblocks);
142 return ERR_PTR(-ENOMEM);
143 - memset (handle, 0, sizeof (handle_t));
145 - handle->h_buffer_credits = nblocks;
147 current->journal_info = handle;
149 err = try_start_this_handle(journal, handle);
150 @@ -1328,6 +1337,28 @@ out:
154 + * Register a callback function for this handle. The function will be
155 + * called when the transaction that this handle is part of has been
156 + * committed to disk with the original callback data struct and the
157 + * error status of the journal as parameters. There is no guarantee of
158 + * ordering between handles within a single transaction, nor between
159 + * callbacks registered on the same handle.
161 + * The caller is responsible for allocating the journal_callback struct.
162 + * This is to allow the caller to add as much extra data to the callback
163 + * as needed, but reduce the overhead of multiple allocations. The caller
164 + * allocated struct must start with a struct journal_callback at offset 0,
165 + * and has the caller-specific data afterwards.
167 +void journal_callback_set(handle_t *handle,
168 + void (*func)(struct journal_callback *jcb, int error),
169 + struct journal_callback *jcb)
171 + list_add(&jcb->jcb_list, &handle->h_jcb);
172 + jcb->jcb_func = func;
176 * All done for a particular handle.
178 * There is not much action needed here. We just return any remaining
179 @@ -1393,7 +1424,10 @@ int journal_stop(handle_t *handle)
180 wake_up(&journal->j_wait_transaction_locked);
184 + /* Move callbacks from the handle to the transaction. */
185 + list_splice(&handle->h_jcb, &transaction->t_jcb);
188 * If the handle is marked SYNC, we need to set another commit
189 * going! We also want to force a commit if the current
190 * transaction is occupying too much of the log, or if the
191 --- linux-2.4.19/include/linux/jbd.h~vanilla-2.4.19 Sun Jan 19 19:46:42 2003
192 +++ linux-2.4.19-root/include/linux/jbd.h Sun Jan 19 19:46:42 2003
193 @@ -249,6 +249,13 @@ static inline struct journal_head *bh2jh
194 return bh->b_private;
197 +#define HAVE_JOURNAL_CALLBACK_STATUS
198 +struct journal_callback {
199 + struct list_head jcb_list;
200 + void (*jcb_func)(struct journal_callback *jcb, int error);
201 + /* user data goes here */
204 struct jbd_revoke_table_s;
206 /* The handle_t type represents a single atomic update being performed
207 @@ -279,6 +286,12 @@ struct handle_s
211 + /* List of application registered callbacks for this handle.
212 + * The function(s) will be called after the transaction that
213 + * this handle is part of has been committed to disk.
215 + struct list_head h_jcb;
218 unsigned int h_sync: 1; /* sync-on-close */
219 unsigned int h_jdata: 1; /* force data journaling */
220 @@ -398,6 +411,10 @@ struct transaction_s
222 /* How many handles used this transaction? */
225 + /* List of registered callback functions for this transaction.
226 + * Called when the transaction is committed. */
227 + struct list_head t_jcb;
231 @@ -646,6 +663,9 @@ extern int journal_flushpage(journal_t
232 extern int journal_try_to_free_buffers(journal_t *, struct page *, int);
233 extern int journal_stop(handle_t *);
234 extern int journal_flush (journal_t *);
235 +extern void journal_callback_set(handle_t *handle,
236 + void (*fn)(struct journal_callback *,int),
237 + struct journal_callback *jcb);
239 extern void journal_lock_updates (journal_t *);
240 extern void journal_unlock_updates (journal_t *);