Skip to content

Commit 932bb30

Browse files
jankaratytso
authored andcommitted
jbd2: remove bh_state lock from checkpointing code
All accesses to checkpointing entries in journal_head are protected by j_list_lock. Thus __jbd2_journal_remove_checkpoint() doesn't really need bh_state lock. Also the only part of journal head that the rest of checkpointing code needs to check is jh->b_transaction which is safe to read under j_list_lock. So we can safely remove bh_state lock from all of checkpointing code which makes it considerably prettier. Signed-off-by: Jan Kara <[email protected]> Signed-off-by: "Theodore Ts'o" <[email protected]>
1 parent c254c9e commit 932bb30

File tree

2 files changed

+9
-52
lines changed

2 files changed

+9
-52
lines changed

fs/jbd2/checkpoint.c

+7-52
Original file line numberDiff line numberDiff line change
@@ -88,14 +88,13 @@ static inline void __buffer_relink_io(struct journal_head *jh)
8888
* whole transaction.
8989
*
9090
* Requires j_list_lock
91-
* Called under jbd_lock_bh_state(jh2bh(jh)), and drops it
9291
*/
9392
static int __try_to_free_cp_buf(struct journal_head *jh)
9493
{
9594
int ret = 0;
9695
struct buffer_head *bh = jh2bh(jh);
9796

98-
if (jh->b_jlist == BJ_None && !buffer_locked(bh) &&
97+
if (jh->b_transaction == NULL && !buffer_locked(bh) &&
9998
!buffer_dirty(bh) && !buffer_write_io_error(bh)) {
10099
/*
101100
* Get our reference so that bh cannot be freed before
@@ -104,11 +103,8 @@ static int __try_to_free_cp_buf(struct journal_head *jh)
104103
get_bh(bh);
105104
JBUFFER_TRACE(jh, "remove from checkpoint list");
106105
ret = __jbd2_journal_remove_checkpoint(jh) + 1;
107-
jbd_unlock_bh_state(bh);
108106
BUFFER_TRACE(bh, "release");
109107
__brelse(bh);
110-
} else {
111-
jbd_unlock_bh_state(bh);
112108
}
113109
return ret;
114110
}
@@ -179,21 +175,6 @@ void __jbd2_log_wait_for_space(journal_t *journal)
179175
}
180176
}
181177

182-
/*
183-
* We were unable to perform jbd_trylock_bh_state() inside j_list_lock.
184-
* The caller must restart a list walk. Wait for someone else to run
185-
* jbd_unlock_bh_state().
186-
*/
187-
static void jbd_sync_bh(journal_t *journal, struct buffer_head *bh)
188-
__releases(journal->j_list_lock)
189-
{
190-
get_bh(bh);
191-
spin_unlock(&journal->j_list_lock);
192-
jbd_lock_bh_state(bh);
193-
jbd_unlock_bh_state(bh);
194-
put_bh(bh);
195-
}
196-
197178
/*
198179
* Clean up transaction's list of buffers submitted for io.
199180
* We wait for any pending IO to complete and remove any clean
@@ -222,15 +203,9 @@ static int __wait_cp_io(journal_t *journal, transaction_t *transaction)
222203
while (!released && transaction->t_checkpoint_io_list) {
223204
jh = transaction->t_checkpoint_io_list;
224205
bh = jh2bh(jh);
225-
if (!jbd_trylock_bh_state(bh)) {
226-
jbd_sync_bh(journal, bh);
227-
spin_lock(&journal->j_list_lock);
228-
goto restart;
229-
}
230206
get_bh(bh);
231207
if (buffer_locked(bh)) {
232208
spin_unlock(&journal->j_list_lock);
233-
jbd_unlock_bh_state(bh);
234209
wait_on_buffer(bh);
235210
/* the journal_head may have gone by now */
236211
BUFFER_TRACE(bh, "brelse");
@@ -246,7 +221,6 @@ static int __wait_cp_io(journal_t *journal, transaction_t *transaction)
246221
* it has been written out and so we can drop it from the list
247222
*/
248223
released = __jbd2_journal_remove_checkpoint(jh);
249-
jbd_unlock_bh_state(bh);
250224
__brelse(bh);
251225
}
252226

@@ -280,7 +254,6 @@ __flush_batch(journal_t *journal, int *batch_count)
280254
* be written out.
281255
*
282256
* Called with j_list_lock held and drops it if 1 is returned
283-
* Called under jbd_lock_bh_state(jh2bh(jh)), and drops it
284257
*/
285258
static int __process_buffer(journal_t *journal, struct journal_head *jh,
286259
int *batch_count, transaction_t *transaction)
@@ -291,7 +264,6 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh,
291264
if (buffer_locked(bh)) {
292265
get_bh(bh);
293266
spin_unlock(&journal->j_list_lock);
294-
jbd_unlock_bh_state(bh);
295267
wait_on_buffer(bh);
296268
/* the journal_head may have gone by now */
297269
BUFFER_TRACE(bh, "brelse");
@@ -303,7 +275,6 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh,
303275

304276
transaction->t_chp_stats.cs_forced_to_close++;
305277
spin_unlock(&journal->j_list_lock);
306-
jbd_unlock_bh_state(bh);
307278
if (unlikely(journal->j_flags & JBD2_UNMOUNT))
308279
/*
309280
* The journal thread is dead; so starting and
@@ -322,11 +293,9 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh,
322293
if (unlikely(buffer_write_io_error(bh)))
323294
ret = -EIO;
324295
get_bh(bh);
325-
J_ASSERT_JH(jh, !buffer_jbddirty(bh));
326296
BUFFER_TRACE(bh, "remove from checkpoint");
327297
__jbd2_journal_remove_checkpoint(jh);
328298
spin_unlock(&journal->j_list_lock);
329-
jbd_unlock_bh_state(bh);
330299
__brelse(bh);
331300
} else {
332301
/*
@@ -341,7 +310,6 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh,
341310
J_ASSERT_BH(bh, !buffer_jwrite(bh));
342311
journal->j_chkpt_bhs[*batch_count] = bh;
343312
__buffer_relink_io(jh);
344-
jbd_unlock_bh_state(bh);
345313
transaction->t_chp_stats.cs_written++;
346314
(*batch_count)++;
347315
if (*batch_count == JBD2_NR_BATCH) {
@@ -405,15 +373,7 @@ int jbd2_log_do_checkpoint(journal_t *journal)
405373
int retry = 0, err;
406374

407375
while (!retry && transaction->t_checkpoint_list) {
408-
struct buffer_head *bh;
409-
410376
jh = transaction->t_checkpoint_list;
411-
bh = jh2bh(jh);
412-
if (!jbd_trylock_bh_state(bh)) {
413-
jbd_sync_bh(journal, bh);
414-
retry = 1;
415-
break;
416-
}
417377
retry = __process_buffer(journal, jh, &batch_count,
418378
transaction);
419379
if (retry < 0 && !result)
@@ -529,15 +489,12 @@ static int journal_clean_one_cp_list(struct journal_head *jh, int *released)
529489
do {
530490
jh = next_jh;
531491
next_jh = jh->b_cpnext;
532-
/* Use trylock because of the ranking */
533-
if (jbd_trylock_bh_state(jh2bh(jh))) {
534-
ret = __try_to_free_cp_buf(jh);
535-
if (ret) {
536-
freed++;
537-
if (ret == 2) {
538-
*released = 1;
539-
return freed;
540-
}
492+
ret = __try_to_free_cp_buf(jh);
493+
if (ret) {
494+
freed++;
495+
if (ret == 2) {
496+
*released = 1;
497+
return freed;
541498
}
542499
}
543500
/*
@@ -620,9 +577,7 @@ int __jbd2_journal_clean_checkpoint_list(journal_t *journal)
620577
* The function can free jh and bh.
621578
*
622579
* This function is called with j_list_lock held.
623-
* This function is called with jbd_lock_bh_state(jh2bh(jh))
624580
*/
625-
626581
int __jbd2_journal_remove_checkpoint(struct journal_head *jh)
627582
{
628583
struct transaction_chp_stats_s *stats;

include/linux/journal-head.h

+2
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ struct journal_head {
6666
* transaction (if there is one). Only applies to buffers on a
6767
* transaction's data or metadata journaling list.
6868
* [j_list_lock] [jbd_lock_bh_state()]
69+
* Either of these locks is enough for reading, both are needed for
70+
* changes.
6971
*/
7072
transaction_t *b_transaction;
7173

0 commit comments

Comments
 (0)