aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jbd2/transaction.c
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2010-08-03 21:38:29 -0400
committerTheodore Ts'o <tytso@mit.edu>2010-08-03 21:38:29 -0400
commit8dd420466c7bfc459fa04680bd5690bfc41a4553 (patch)
tree6004eaaa7266979397a9d87e30066fc91d3650c3 /fs/jbd2/transaction.c
parenta931da6ac9331a6c80dd91c199105806f2336188 (diff)
jbd2: Remove t_handle_lock from start_this_handle()
This should remove the last exclusive lock from start_this_handle(), so that we should now be able to start multiple transactions at the same time on large SMP systems. Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/jbd2/transaction.c')
-rw-r--r--fs/jbd2/transaction.c33
1 files changed, 22 insertions, 11 deletions
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
index 663065142b42..0752bcda535f 100644
--- a/fs/jbd2/transaction.c
+++ b/fs/jbd2/transaction.c
@@ -57,6 +57,7 @@ jbd2_get_transaction(journal_t *journal, transaction_t *transaction)
57 spin_lock_init(&transaction->t_handle_lock); 57 spin_lock_init(&transaction->t_handle_lock);
58 atomic_set(&transaction->t_updates, 0); 58 atomic_set(&transaction->t_updates, 0);
59 atomic_set(&transaction->t_outstanding_credits, 0); 59 atomic_set(&transaction->t_outstanding_credits, 0);
60 atomic_set(&transaction->t_handle_count, 0);
60 INIT_LIST_HEAD(&transaction->t_inode_list); 61 INIT_LIST_HEAD(&transaction->t_inode_list);
61 INIT_LIST_HEAD(&transaction->t_private_list); 62 INIT_LIST_HEAD(&transaction->t_private_list);
62 63
@@ -180,8 +181,8 @@ repeat:
180 * buffers requested by this operation, we need to stall pending a log 181 * buffers requested by this operation, we need to stall pending a log
181 * checkpoint to free some more log space. 182 * checkpoint to free some more log space.
182 */ 183 */
183 spin_lock(&transaction->t_handle_lock); 184 needed = atomic_add_return(nblocks,
184 needed = atomic_read(&transaction->t_outstanding_credits) + nblocks; 185 &transaction->t_outstanding_credits);
185 186
186 if (needed > journal->j_max_transaction_buffers) { 187 if (needed > journal->j_max_transaction_buffers) {
187 /* 188 /*
@@ -192,7 +193,7 @@ repeat:
192 DEFINE_WAIT(wait); 193 DEFINE_WAIT(wait);
193 194
194 jbd_debug(2, "Handle %p starting new commit...\n", handle); 195 jbd_debug(2, "Handle %p starting new commit...\n", handle);
195 spin_unlock(&transaction->t_handle_lock); 196 atomic_sub(nblocks, &transaction->t_outstanding_credits);
196 prepare_to_wait(&journal->j_wait_transaction_locked, &wait, 197 prepare_to_wait(&journal->j_wait_transaction_locked, &wait,
197 TASK_UNINTERRUPTIBLE); 198 TASK_UNINTERRUPTIBLE);
198 __jbd2_log_start_commit(journal, transaction->t_tid); 199 __jbd2_log_start_commit(journal, transaction->t_tid);
@@ -229,7 +230,7 @@ repeat:
229 */ 230 */
230 if (__jbd2_log_space_left(journal) < jbd_space_needed(journal)) { 231 if (__jbd2_log_space_left(journal) < jbd_space_needed(journal)) {
231 jbd_debug(2, "Handle %p waiting for checkpoint...\n", handle); 232 jbd_debug(2, "Handle %p waiting for checkpoint...\n", handle);
232 spin_unlock(&transaction->t_handle_lock); 233 atomic_sub(nblocks, &transaction->t_outstanding_credits);
233 read_unlock(&journal->j_state_lock); 234 read_unlock(&journal->j_state_lock);
234 write_lock(&journal->j_state_lock); 235 write_lock(&journal->j_state_lock);
235 if (__jbd2_log_space_left(journal) < jbd_space_needed(journal)) 236 if (__jbd2_log_space_left(journal) < jbd_space_needed(journal))
@@ -239,23 +240,33 @@ repeat:
239 } 240 }
240 241
241 /* OK, account for the buffers that this operation expects to 242 /* OK, account for the buffers that this operation expects to
242 * use and add the handle to the running transaction. */ 243 * use and add the handle to the running transaction.
243 244 *
244 if (time_after(transaction->t_start, ts)) { 245 * In order for t_max_wait to be reliable, it must be
246 * protected by a lock. But doing so will mean that
247 * start_this_handle() can not be run in parallel on SMP
248 * systems, which limits our scalability. So we only enable
249 * it when debugging is enabled. We may want to use a
250 * separate flag, eventually, so we can enable this
251 * independently of debugging.
252 */
253#ifdef CONFIG_JBD2_DEBUG
254 if (jbd2_journal_enable_debug &&
255 time_after(transaction->t_start, ts)) {
245 ts = jbd2_time_diff(ts, transaction->t_start); 256 ts = jbd2_time_diff(ts, transaction->t_start);
257 spin_lock(&transaction->t_handle_lock);
246 if (ts > transaction->t_max_wait) 258 if (ts > transaction->t_max_wait)
247 transaction->t_max_wait = ts; 259 transaction->t_max_wait = ts;
260 spin_unlock(&transaction->t_handle_lock);
248 } 261 }
249 262#endif
250 handle->h_transaction = transaction; 263 handle->h_transaction = transaction;
251 atomic_add(nblocks, &transaction->t_outstanding_credits);
252 atomic_inc(&transaction->t_updates); 264 atomic_inc(&transaction->t_updates);
253 transaction->t_handle_count++; 265 atomic_inc(&transaction->t_handle_count);
254 jbd_debug(4, "Handle %p given %d credits (total %d, free %d)\n", 266 jbd_debug(4, "Handle %p given %d credits (total %d, free %d)\n",
255 handle, nblocks, 267 handle, nblocks,
256 atomic_read(&transaction->t_outstanding_credits), 268 atomic_read(&transaction->t_outstanding_credits),
257 __jbd2_log_space_left(journal)); 269 __jbd2_log_space_left(journal));
258 spin_unlock(&transaction->t_handle_lock);
259 read_unlock(&journal->j_state_lock); 270 read_unlock(&journal->j_state_lock);
260 271
261 lock_map_acquire(&handle->h_lockdep_map); 272 lock_map_acquire(&handle->h_lockdep_map);