]>
Commit | Line | Data |
---|---|---|
c80d6cf3 | 1 | Index: linux-2.6/include/linux/jbd.h |
2 | =================================================================== | |
3 | --- linux-2.6.orig/include/linux/jbd.h 2006-07-15 16:08:35.000000000 +0800 | |
4 | +++ linux-2.6/include/linux/jbd.h 2006-07-15 16:13:01.000000000 +0800 | |
5 | @@ -356,6 +356,27 @@ static inline void jbd_unlock_bh_journal | |
6 | bit_spin_unlock(BH_JournalHead, &bh->b_state); | |
7 | } | |
8 | ||
9 | +#define HAVE_JOURNAL_CALLBACK_STATUS | |
10 | +/** | |
11 | + * struct journal_callback - Base structure for callback information. | |
12 | + * @jcb_list: list information for other callbacks attached to the same handle. | |
13 | + * @jcb_func: Function to call with this callback structure. | |
14 | + * | |
15 | + * This struct is a 'seed' structure for a using with your own callback | |
16 | + * structs. If you are using callbacks you must allocate one of these | |
17 | + * or another struct of your own definition which has this struct | |
18 | + * as it's first element and pass it to journal_callback_set(). | |
19 | + * | |
20 | + * This is used internally by jbd to maintain callback information. | |
21 | + * | |
22 | + * See journal_callback_set for more information. | |
23 | + **/ | |
24 | +struct journal_callback { | |
25 | + struct list_head jcb_list; /* t_jcb_lock */ | |
26 | + void (*jcb_func)(struct journal_callback *jcb, int error); | |
27 | + /* user data goes here */ | |
28 | +}; | |
29 | + | |
30 | struct jbd_revoke_table_s; | |
31 | ||
32 | /** | |
33 | @@ -364,6 +385,7 @@ struct jbd_revoke_table_s; | |
34 | * @h_transaction: Which compound transaction is this update a part of? | |
35 | * @h_buffer_credits: Number of remaining buffers we are allowed to dirty. | |
36 | * @h_ref: Reference count on this handle | |
37 | + * @h_jcb: List of application registered callbacks for this handle. | |
38 | * @h_err: Field for caller's use to track errors through large fs operations | |
39 | * @h_sync: flag for sync-on-close | |
40 | * @h_jdata: flag to force data journaling | |
41 | @@ -389,6 +411,13 @@ struct handle_s | |
42 | /* operations */ | |
43 | int h_err; | |
44 | ||
45 | + /* | |
46 | + * List of application registered callbacks for this handle. The | |
47 | + * function(s) will be called after the transaction that this handle is | |
48 | + * part of has been committed to disk. [t_jcb_lock] | |
49 | + */ | |
50 | + struct list_head h_jcb; | |
51 | + | |
52 | /* Flags [no locking] */ | |
53 | unsigned int h_sync: 1; /* sync-on-close */ | |
54 | unsigned int h_jdata: 1; /* force data journaling */ | |
55 | @@ -430,6 +459,8 @@ struct handle_s | |
56 | * j_state_lock | |
57 | * ->j_list_lock (journal_unmap_buffer) | |
58 | * | |
59 | + * t_handle_lock | |
60 | + * ->t_jcb_lock | |
61 | */ | |
62 | ||
63 | struct transaction_s | |
64 | @@ -559,6 +590,15 @@ struct transaction_s | |
65 | */ | |
66 | int t_handle_count; | |
67 | ||
68 | + /* | |
69 | + * Protects the callback list | |
70 | + */ | |
71 | + spinlock_t t_jcb_lock; | |
72 | + /* | |
73 | + * List of registered callback functions for this transaction. | |
74 | + * Called when the transaction is committed. [t_jcb_lock] | |
75 | + */ | |
76 | + struct list_head t_jcb; | |
77 | }; | |
78 | ||
79 | /** | |
80 | @@ -906,6 +946,10 @@ extern void journal_invalidatepage(jour | |
81 | extern int journal_try_to_free_buffers(journal_t *, struct page *, gfp_t); | |
82 | extern int journal_stop(handle_t *); | |
83 | extern int journal_flush (journal_t *); | |
84 | +extern void journal_callback_set(handle_t *handle, | |
85 | + void (*fn)(struct journal_callback *,int), | |
86 | + struct journal_callback *jcb); | |
87 | + | |
88 | extern void journal_lock_updates (journal_t *); | |
89 | extern void journal_unlock_updates (journal_t *); | |
90 | ||
91 | Index: linux-2.6/fs/jbd/checkpoint.c | |
92 | =================================================================== | |
93 | --- linux-2.6.orig/fs/jbd/checkpoint.c 2006-07-15 16:08:36.000000000 +0800 | |
94 | +++ linux-2.6/fs/jbd/checkpoint.c 2006-07-15 16:13:01.000000000 +0800 | |
95 | @@ -688,6 +688,7 @@ void __journal_drop_transaction(journal_ | |
96 | J_ASSERT(transaction->t_checkpoint_list == NULL); | |
97 | J_ASSERT(transaction->t_checkpoint_io_list == NULL); | |
98 | J_ASSERT(transaction->t_updates == 0); | |
99 | + J_ASSERT(list_empty(&transaction->t_jcb)); | |
100 | J_ASSERT(journal->j_committing_transaction != transaction); | |
101 | J_ASSERT(journal->j_running_transaction != transaction); | |
102 | ||
103 | Index: linux-2.6/fs/jbd/commit.c | |
104 | =================================================================== | |
105 | --- linux-2.6.orig/fs/jbd/commit.c 2006-07-15 16:08:36.000000000 +0800 | |
106 | +++ linux-2.6/fs/jbd/commit.c 2006-07-15 16:13:01.000000000 +0800 | |
107 | @@ -708,6 +708,30 @@ wait_for_iobuf: | |
108 | transaction can be removed from any checkpoint list it was on | |
109 | before. */ | |
110 | ||
111 | + /* | |
112 | + * Call any callbacks that had been registered for handles in this | |
113 | + * transaction. It is up to the callback to free any allocated | |
114 | + * memory. | |
115 | + * | |
116 | + * The spinlocking (t_jcb_lock) here is surely unnecessary... | |
117 | + */ | |
118 | + spin_lock(&commit_transaction->t_jcb_lock); | |
119 | + if (!list_empty(&commit_transaction->t_jcb)) { | |
120 | + struct list_head *p, *n; | |
121 | + int error = is_journal_aborted(journal); | |
122 | + | |
123 | + list_for_each_safe(p, n, &commit_transaction->t_jcb) { | |
124 | + struct journal_callback *jcb; | |
125 | + | |
126 | + jcb = list_entry(p, struct journal_callback, jcb_list); | |
127 | + list_del(p); | |
128 | + spin_unlock(&commit_transaction->t_jcb_lock); | |
129 | + jcb->jcb_func(jcb, error); | |
130 | + spin_lock(&commit_transaction->t_jcb_lock); | |
131 | + } | |
132 | + } | |
133 | + spin_unlock(&commit_transaction->t_jcb_lock); | |
134 | + | |
135 | jbd_debug(3, "JBD: commit phase 7\n"); | |
136 | ||
137 | J_ASSERT(commit_transaction->t_sync_datalist == NULL); | |
138 | Index: linux-2.6/fs/jbd/journal.c | |
139 | =================================================================== | |
140 | --- linux-2.6.orig/fs/jbd/journal.c 2006-07-15 16:08:36.000000000 +0800 | |
141 | +++ linux-2.6/fs/jbd/journal.c 2006-07-15 16:13:01.000000000 +0800 | |
142 | @@ -58,6 +58,7 @@ EXPORT_SYMBOL(journal_sync_buffer); | |
143 | #endif | |
144 | EXPORT_SYMBOL(journal_flush); | |
145 | EXPORT_SYMBOL(journal_revoke); | |
146 | +EXPORT_SYMBOL(journal_callback_set); | |
147 | ||
148 | EXPORT_SYMBOL(journal_init_dev); | |
149 | EXPORT_SYMBOL(journal_init_inode); | |
150 | @@ -80,6 +81,7 @@ EXPORT_SYMBOL(journal_wipe); | |
151 | EXPORT_SYMBOL(journal_blocks_per_page); | |
152 | EXPORT_SYMBOL(journal_invalidatepage); | |
153 | EXPORT_SYMBOL(journal_try_to_free_buffers); | |
154 | +EXPORT_SYMBOL(journal_bmap); | |
155 | EXPORT_SYMBOL(journal_force_commit); | |
156 | ||
157 | static int journal_convert_superblock_v1(journal_t *, journal_superblock_t *); | |
158 | Index: linux-2.6/fs/jbd/transaction.c | |
159 | =================================================================== | |
160 | --- linux-2.6.orig/fs/jbd/transaction.c 2006-07-15 16:08:35.000000000 +0800 | |
161 | +++ linux-2.6/fs/jbd/transaction.c 2006-07-15 16:13:01.000000000 +0800 | |
162 | @@ -50,7 +50,9 @@ get_transaction(journal_t *journal, tran | |
163 | transaction->t_state = T_RUNNING; | |
164 | transaction->t_tid = journal->j_transaction_sequence++; | |
165 | transaction->t_expires = jiffies + journal->j_commit_interval; | |
166 | + INIT_LIST_HEAD(&transaction->t_jcb); | |
167 | spin_lock_init(&transaction->t_handle_lock); | |
168 | + spin_lock_init(&transaction->t_jcb_lock); | |
169 | ||
170 | /* Set up the commit timer for the new transaction. */ | |
171 | journal->j_commit_timer.expires = transaction->t_expires; | |
172 | @@ -241,6 +243,7 @@ static handle_t *new_handle(int nblocks) | |
173 | memset(handle, 0, sizeof(*handle)); | |
174 | handle->h_buffer_credits = nblocks; | |
175 | handle->h_ref = 1; | |
176 | + INIT_LIST_HEAD(&handle->h_jcb); | |
177 | ||
178 | return handle; | |
179 | } | |
180 | @@ -1291,6 +1294,36 @@ drop: | |
181 | } | |
182 | ||
183 | /** | |
184 | + * void journal_callback_set() - Register a callback function for this handle. | |
185 | + * @handle: handle to attach the callback to. | |
186 | + * @func: function to callback. | |
187 | + * @jcb: structure with additional information required by func() , and | |
188 | + * some space for jbd internal information. | |
189 | + * | |
190 | + * The function will be | |
191 | + * called when the transaction that this handle is part of has been | |
192 | + * committed to disk with the original callback data struct and the | |
193 | + * error status of the journal as parameters. There is no guarantee of | |
194 | + * ordering between handles within a single transaction, nor between | |
195 | + * callbacks registered on the same handle. | |
196 | + * | |
197 | + * The caller is responsible for allocating the journal_callback struct. | |
198 | + * This is to allow the caller to add as much extra data to the callback | |
199 | + * as needed, but reduce the overhead of multiple allocations. The caller | |
200 | + * allocated struct must start with a struct journal_callback at offset 0, | |
201 | + * and has the caller-specific data afterwards. | |
202 | + */ | |
203 | +void journal_callback_set(handle_t *handle, | |
204 | + void (*func)(struct journal_callback *jcb, int error), | |
205 | + struct journal_callback *jcb) | |
206 | +{ | |
207 | + spin_lock(&handle->h_transaction->t_jcb_lock); | |
208 | + list_add_tail(&jcb->jcb_list, &handle->h_jcb); | |
209 | + spin_unlock(&handle->h_transaction->t_jcb_lock); | |
210 | + jcb->jcb_func = func; | |
211 | +} | |
212 | + | |
213 | +/** | |
214 | * int journal_stop() - complete a transaction | |
215 | * @handle: tranaction to complete. | |
216 | * | |
217 | @@ -1363,6 +1396,11 @@ int journal_stop(handle_t *handle) | |
218 | wake_up(&journal->j_wait_transaction_locked); | |
219 | } | |
220 | ||
221 | + /* Move callbacks from the handle to the transaction. */ | |
222 | + spin_lock(&transaction->t_jcb_lock); | |
223 | + list_splice(&handle->h_jcb, &transaction->t_jcb); | |
224 | + spin_unlock(&transaction->t_jcb_lock); | |
225 | + | |
226 | /* | |
227 | * If the handle is marked SYNC, we need to set another commit | |
228 | * going! We also want to force a commit if the current |