1 This patch is no longer needed for Lustre, since Lustre 2.2. It is kept
2 in the kernel patch series for compatibility with older Lustre releases
3 to simplify the upgrade process so that both the kernel and Lustre do
4 not need to be upgraded at the same time. See Jira issue LU-433.
6 Index: linux-2.6.27.21-0.1/include/linux/jbd2.h
7 ===================================================================
8 --- linux-2.6.27.21-0.1.orig/include/linux/jbd2.h
9 +++ linux-2.6.27.21-0.1/include/linux/jbd2.h
10 @@ -413,6 +413,27 @@ struct jbd2_inode {
14 +#define HAVE_JOURNAL_CALLBACK_STATUS
16 + * struct journal_callback - Base structure for callback information.
17 + * @jcb_list: list information for other callbacks attached to the same handle.
18 + * @jcb_func: Function to call with this callback structure.
20 + * This struct is a 'seed' structure for a using with your own callback
21 + * structs. If you are using callbacks you must allocate one of these
22 + * or another struct of your own definition which has this struct
23 + * as it's first element and pass it to journal_callback_set().
25 + * This is used internally by jbd2 to maintain callback information.
27 + * See journal_callback_set for more information.
29 +struct journal_callback {
30 + struct list_head jcb_list; /* t_jcb_lock */
31 + void (*jcb_func)(struct journal_callback *jcb, int error);
32 + /* user data goes here */
35 struct jbd2_revoke_table_s;
38 @@ -421,6 +442,7 @@ struct jbd2_revoke_table_s;
39 * @h_transaction: Which compound transaction is this update a part of?
40 * @h_buffer_credits: Number of remaining buffers we are allowed to dirty.
41 * @h_ref: Reference count on this handle
42 + * @h_jcb: List of application registered callbacks for this handle.
43 * @h_err: Field for caller's use to track errors through large fs operations
44 * @h_sync: flag for sync-on-close
45 * @h_jdata: flag to force data journaling
46 @@ -446,6 +468,13 @@ struct handle_s
51 + * List of application registered callbacks for this handle. The
52 + * function(s) will be called after the transaction that this handle is
53 + * part of has been committed to disk. [t_jcb_lock]
55 + struct list_head h_jcb;
57 /* Flags [no locking] */
58 unsigned int h_sync: 1; /* sync-on-close */
59 unsigned int h_jdata: 1; /* force data journaling */
60 @@ -501,6 +530,8 @@ struct transaction_chp_stats_s {
62 * ->j_list_lock (journal_unmap_buffer)
69 @@ -641,6 +672,15 @@ struct transaction_s
74 + * Protects the callback list
76 + spinlock_t t_jcb_lock;
78 + * List of registered callback functions for this transaction.
79 + * Called when the transaction is committed. [t_jcb_lock]
81 + struct list_head t_jcb;
84 struct transaction_run_stats_s {
85 @@ -1044,6 +1084,9 @@ extern int jbd2_journal_stop(handle_t *
86 extern int jbd2_journal_flush (journal_t *);
87 extern void jbd2_journal_lock_updates (journal_t *);
88 extern void jbd2_journal_unlock_updates (journal_t *);
89 +extern void jbd2_journal_callback_set(handle_t *handle,
90 + void (*fn)(struct journal_callback *,int),
91 + struct journal_callback *jcb);
93 extern journal_t * jbd2_journal_init_dev(struct block_device *bdev,
94 struct block_device *fs_dev,
95 Index: linux-2.6.27.21-0.1/fs/jbd2/checkpoint.c
96 ===================================================================
97 --- linux-2.6.27.21-0.1.orig/fs/jbd2/checkpoint.c
98 +++ linux-2.6.27.21-0.1/fs/jbd2/checkpoint.c
99 @@ -728,6 +728,7 @@ void __jbd2_journal_drop_transaction(jou
100 J_ASSERT(transaction->t_checkpoint_list == NULL);
101 J_ASSERT(transaction->t_checkpoint_io_list == NULL);
102 J_ASSERT(transaction->t_updates == 0);
103 + J_ASSERT(list_empty(&transaction->t_jcb));
104 J_ASSERT(journal->j_committing_transaction != transaction);
105 J_ASSERT(journal->j_running_transaction != transaction);
107 Index: linux-2.6.27.21-0.1/fs/jbd2/commit.c
108 ===================================================================
109 --- linux-2.6.27.21-0.1.orig/fs/jbd2/commit.c
110 +++ linux-2.6.27.21-0.1/fs/jbd2/commit.c
111 @@ -805,6 +805,30 @@ wait_for_iobuf:
112 transaction can be removed from any checkpoint list it was on
116 + * Call any callbacks that had been registered for handles in this
117 + * transaction. It is up to the callback to free any allocated
120 + * The spinlocking (t_jcb_lock) here is surely unnecessary...
122 + spin_lock(&commit_transaction->t_jcb_lock);
123 + if (!list_empty(&commit_transaction->t_jcb)) {
124 + struct list_head *p, *n;
125 + int error = is_journal_aborted(journal);
127 + list_for_each_safe(p, n, &commit_transaction->t_jcb) {
128 + struct journal_callback *jcb;
130 + jcb = list_entry(p, struct journal_callback, jcb_list);
132 + spin_unlock(&commit_transaction->t_jcb_lock);
133 + jcb->jcb_func(jcb, error);
134 + spin_lock(&commit_transaction->t_jcb_lock);
137 + spin_unlock(&commit_transaction->t_jcb_lock);
139 jbd_debug(3, "JBD: commit phase 6\n");
141 J_ASSERT(list_empty(&commit_transaction->t_inode_list));
142 Index: linux-2.6.27.21-0.1/fs/jbd2/journal.c
143 ===================================================================
144 --- linux-2.6.27.21-0.1.orig/fs/jbd2/journal.c
145 +++ linux-2.6.27.21-0.1/fs/jbd2/journal.c
146 @@ -84,6 +84,8 @@ EXPORT_SYMBOL(jbd2_journal_file_inode);
147 EXPORT_SYMBOL(jbd2_journal_init_jbd_inode);
148 EXPORT_SYMBOL(jbd2_journal_release_jbd_inode);
149 EXPORT_SYMBOL(jbd2_journal_begin_ordered_truncate);
150 +EXPORT_SYMBOL(jbd2_journal_callback_set);
151 +EXPORT_SYMBOL(jbd2_journal_bmap);
153 static int journal_convert_superblock_v1(journal_t *, journal_superblock_t *);
154 static void __journal_abort_soft (journal_t *journal, int errno);
155 Index: linux-2.6.27.21-0.1/fs/jbd2/transaction.c
156 ===================================================================
157 --- linux-2.6.27.21-0.1.orig/fs/jbd2/transaction.c
158 +++ linux-2.6.27.21-0.1/fs/jbd2/transaction.c
159 @@ -50,7 +50,9 @@ jbd2_get_transaction(journal_t *journal,
160 transaction->t_state = T_RUNNING;
161 transaction->t_tid = journal->j_transaction_sequence++;
162 transaction->t_expires = jiffies + journal->j_commit_interval;
163 + INIT_LIST_HEAD(&transaction->t_jcb);
164 spin_lock_init(&transaction->t_handle_lock);
165 + spin_lock_init(&transaction->t_jcb_lock);
166 INIT_LIST_HEAD(&transaction->t_inode_list);
168 /* Set up the commit timer for the new transaction. */
169 @@ -252,6 +254,7 @@ static handle_t *new_handle(int nblocks)
170 memset(handle, 0, sizeof(*handle));
171 handle->h_buffer_credits = nblocks;
173 + INIT_LIST_HEAD(&handle->h_jcb);
175 lockdep_init_map(&handle->h_lockdep_map, "jbd2_handle",
176 &jbd2_handle_key, 0);
177 @@ -1173,6 +1176,36 @@ drop:
181 + * void jbd2_journal_callback_set() - Register a callback function for this handle.
182 + * @handle: handle to attach the callback to.
183 + * @func: function to callback.
184 + * @jcb: structure with additional information required by func() , and
185 + * some space for jbd2 internal information.
187 + * The function will be
188 + * called when the transaction that this handle is part of has been
189 + * committed to disk with the original callback data struct and the
190 + * error status of the journal as parameters. There is no guarantee of
191 + * ordering between handles within a single transaction, nor between
192 + * callbacks registered on the same handle.
194 + * The caller is responsible for allocating the journal_callback struct.
195 + * This is to allow the caller to add as much extra data to the callback
196 + * as needed, but reduce the overhead of multiple allocations. The caller
197 + * allocated struct must start with a struct journal_callback at offset 0,
198 + * and has the caller-specific data afterwards.
200 +void jbd2_journal_callback_set(handle_t *handle,
201 + void (*func)(struct journal_callback *jcb, int error),
202 + struct journal_callback *jcb)
204 + spin_lock(&handle->h_transaction->t_jcb_lock);
205 + list_add_tail(&jcb->jcb_list, &handle->h_jcb);
206 + spin_unlock(&handle->h_transaction->t_jcb_lock);
207 + jcb->jcb_func = func;
211 * int jbd2_journal_stop() - complete a transaction
212 * @handle: tranaction to complete.
214 @@ -1246,6 +1279,11 @@ int jbd2_journal_stop(handle_t *handle)
215 wake_up(&journal->j_wait_transaction_locked);
218 + /* Move callbacks from the handle to the transaction. */
219 + spin_lock(&transaction->t_jcb_lock);
220 + list_splice(&handle->h_jcb, &transaction->t_jcb);
221 + spin_unlock(&transaction->t_jcb_lock);
224 * If the handle is marked SYNC, we need to set another commit
225 * going! We also want to force a commit if the current