jbd2: Make state lock a spinlock
Bit-spinlocks are problematic on PREEMPT_RT if functions which might sleep on RT, e.g. spin_lock(), alloc/free(), are invoked inside the lock held region because bit spinlocks disable preemption even on RT. A first attempt was to replace state lock with a spinlock placed in struct buffer_head and make the locking conditional on PREEMPT_RT and DEBUG_BIT_SPINLOCKS. Jan pointed out that there is a 4 byte hole in struct journal_head where a regular spinlock fits in and he would not object to convert the state lock to a spinlock unconditionally. Aside of solving the RT problem, this also gains lockdep coverage for the journal head state lock (bit-spinlocks are not covered by lockdep as it's hard to fit a lockdep map into a single bit). The trivial change would have been to convert the jbd_*lock_bh_state() inlines, but that comes with the downside that these functions take a buffer head pointer which needs to be converted to a journal head pointer which adds another level of indirection. As almost all functions which use this lock have a journal head pointer readily available, it makes more sense to remove the lock helper inlines and write out spin_*lock() at all call sites. Fixup all locking comments as well. Suggested-by: Jan Kara <jack@suse.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Jan Kara <jack@suse.cz> Cc: "Theodore Ts'o" <tytso@mit.edu> Cc: Mark Fasheh <mark@fasheh.com> Cc: Joseph Qi <joseph.qi@linux.alibaba.com> Cc: Joel Becker <jlbec@evilplan.org> Cc: Jan Kara <jack@suse.com> Cc: linux-ext4@vger.kernel.org Link: https://lore.kernel.org/r/20190809124233.13277-7-jack@suse.cz Signed-off-by: Theodore Ts'o <tytso@mit.edu>
This commit is contained in:

committed by
Theodore Ts'o

parent
2e710ff03f
commit
464170647b
@@ -1252,6 +1252,7 @@ static int ocfs2_test_bg_bit_allocatable(struct buffer_head *bg_bh,
|
||||
int nr)
|
||||
{
|
||||
struct ocfs2_group_desc *bg = (struct ocfs2_group_desc *) bg_bh->b_data;
|
||||
struct journal_head *jh;
|
||||
int ret;
|
||||
|
||||
if (ocfs2_test_bit(nr, (unsigned long *)bg->bg_bitmap))
|
||||
@@ -1260,13 +1261,14 @@ static int ocfs2_test_bg_bit_allocatable(struct buffer_head *bg_bh,
|
||||
if (!buffer_jbd(bg_bh))
|
||||
return 1;
|
||||
|
||||
jbd_lock_bh_state(bg_bh);
|
||||
bg = (struct ocfs2_group_desc *) bh2jh(bg_bh)->b_committed_data;
|
||||
jh = bh2jh(bg_bh);
|
||||
spin_lock(&jh->b_state_lock);
|
||||
bg = (struct ocfs2_group_desc *) jh->b_committed_data;
|
||||
if (bg)
|
||||
ret = !ocfs2_test_bit(nr, (unsigned long *)bg->bg_bitmap);
|
||||
else
|
||||
ret = 1;
|
||||
jbd_unlock_bh_state(bg_bh);
|
||||
spin_unlock(&jh->b_state_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -2387,6 +2389,7 @@ static int ocfs2_block_group_clear_bits(handle_t *handle,
|
||||
int status;
|
||||
unsigned int tmp;
|
||||
struct ocfs2_group_desc *undo_bg = NULL;
|
||||
struct journal_head *jh;
|
||||
|
||||
/* The caller got this descriptor from
|
||||
* ocfs2_read_group_descriptor(). Any corruption is a code bug. */
|
||||
@@ -2405,10 +2408,10 @@ static int ocfs2_block_group_clear_bits(handle_t *handle,
|
||||
goto bail;
|
||||
}
|
||||
|
||||
jh = bh2jh(group_bh);
|
||||
if (undo_fn) {
|
||||
jbd_lock_bh_state(group_bh);
|
||||
undo_bg = (struct ocfs2_group_desc *)
|
||||
bh2jh(group_bh)->b_committed_data;
|
||||
spin_lock(&jh->b_state_lock);
|
||||
undo_bg = (struct ocfs2_group_desc *) jh->b_committed_data;
|
||||
BUG_ON(!undo_bg);
|
||||
}
|
||||
|
||||
@@ -2423,7 +2426,7 @@ static int ocfs2_block_group_clear_bits(handle_t *handle,
|
||||
le16_add_cpu(&bg->bg_free_bits_count, num_bits);
|
||||
if (le16_to_cpu(bg->bg_free_bits_count) > le16_to_cpu(bg->bg_bits)) {
|
||||
if (undo_fn)
|
||||
jbd_unlock_bh_state(group_bh);
|
||||
spin_unlock(&jh->b_state_lock);
|
||||
return ocfs2_error(alloc_inode->i_sb, "Group descriptor # %llu has bit count %u but claims %u are freed. num_bits %d\n",
|
||||
(unsigned long long)le64_to_cpu(bg->bg_blkno),
|
||||
le16_to_cpu(bg->bg_bits),
|
||||
@@ -2432,7 +2435,7 @@ static int ocfs2_block_group_clear_bits(handle_t *handle,
|
||||
}
|
||||
|
||||
if (undo_fn)
|
||||
jbd_unlock_bh_state(group_bh);
|
||||
spin_unlock(&jh->b_state_lock);
|
||||
|
||||
ocfs2_journal_dirty(handle, group_bh);
|
||||
bail:
|
||||
|
Reference in New Issue
Block a user