Skip to content

Commit 5f4403e

Browse files
Ioannis Angelakopouloskdave
authored andcommitted
btrfs: add lockdep annotations for the ordered extents wait event
This wait event is very similar to the pending ordered wait event in the sense that it occurs in a different context than the condition signaling for the event. The signaling occurs in btrfs_remove_ordered_extent() while the wait event is implemented in btrfs_start_ordered_extent() in fs/btrfs/ordered-data.c However, in this case a thread must not acquire the lockdep map for the ordered extents wait event when the ordered extent is related to a free space inode. That is because lockdep creates dependencies between locks acquired both in execution paths related to normal inodes and paths related to free space inodes, thus leading to false positives. Reviewed-by: Josef Bacik <[email protected]> Signed-off-by: Ioannis Angelakopoulos <[email protected]> Reviewed-by: David Sterba <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent 9d7464c commit 5f4403e

File tree

4 files changed

+33
-0
lines changed

4 files changed

+33
-0
lines changed

fs/btrfs/ctree.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1100,6 +1100,7 @@ struct btrfs_fs_info {
11001100
struct lockdep_map btrfs_trans_num_extwriters_map;
11011101
struct lockdep_map btrfs_state_change_map[4];
11021102
struct lockdep_map btrfs_trans_pending_ordered_map;
1103+
struct lockdep_map btrfs_ordered_extent_map;
11031104

11041105
#ifdef CONFIG_BTRFS_FS_REF_VERIFY
11051106
spinlock_t ref_verify_lock;

fs/btrfs/disk-io.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2993,6 +2993,7 @@ void btrfs_init_fs_info(struct btrfs_fs_info *fs_info)
29932993
btrfs_lockdep_init_map(fs_info, btrfs_trans_num_writers);
29942994
btrfs_lockdep_init_map(fs_info, btrfs_trans_num_extwriters);
29952995
btrfs_lockdep_init_map(fs_info, btrfs_trans_pending_ordered);
2996+
btrfs_lockdep_init_map(fs_info, btrfs_ordered_extent);
29962997
btrfs_state_lockdep_init_map(fs_info, btrfs_trans_commit_start,
29972998
BTRFS_LOCKDEP_TRANS_COMMIT_START);
29982999
btrfs_state_lockdep_init_map(fs_info, btrfs_trans_unblocked,

fs/btrfs/inode.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3225,6 +3225,8 @@ int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
32253225
clear_bits |= EXTENT_DELALLOC_NEW;
32263226

32273227
freespace_inode = btrfs_is_free_space_inode(inode);
3228+
if (!freespace_inode)
3229+
btrfs_lockdep_acquire(fs_info, btrfs_ordered_extent);
32283230

32293231
if (test_bit(BTRFS_ORDERED_IOERR, &ordered_extent->flags)) {
32303232
ret = -EIO;
@@ -8959,6 +8961,7 @@ void btrfs_destroy_inode(struct inode *vfs_inode)
89598961
struct btrfs_ordered_extent *ordered;
89608962
struct btrfs_inode *inode = BTRFS_I(vfs_inode);
89618963
struct btrfs_root *root = inode->root;
8964+
bool freespace_inode;
89628965

89638966
WARN_ON(!hlist_empty(&vfs_inode->i_dentry));
89648967
WARN_ON(vfs_inode->i_data.nrpages);
@@ -8980,6 +8983,12 @@ void btrfs_destroy_inode(struct inode *vfs_inode)
89808983
if (!root)
89818984
return;
89828985

8986+
/*
8987+
* If this is a free space inode do not take the ordered extents lockdep
8988+
* map.
8989+
*/
8990+
freespace_inode = btrfs_is_free_space_inode(inode);
8991+
89838992
while (1) {
89848993
ordered = btrfs_lookup_first_ordered_extent(inode, (u64)-1);
89858994
if (!ordered)
@@ -8988,6 +8997,10 @@ void btrfs_destroy_inode(struct inode *vfs_inode)
89888997
btrfs_err(root->fs_info,
89898998
"found ordered extent %llu %llu on inode cleanup",
89908999
ordered->file_offset, ordered->num_bytes);
9000+
9001+
if (!freespace_inode)
9002+
btrfs_lockdep_acquire(root->fs_info, btrfs_ordered_extent);
9003+
89919004
btrfs_remove_ordered_extent(inode, ordered);
89929005
btrfs_put_ordered_extent(ordered);
89939006
btrfs_put_ordered_extent(ordered);

fs/btrfs/ordered-data.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,13 @@ void btrfs_remove_ordered_extent(struct btrfs_inode *btrfs_inode,
524524
struct btrfs_fs_info *fs_info = root->fs_info;
525525
struct rb_node *node;
526526
bool pending;
527+
bool freespace_inode;
528+
529+
/*
530+
* If this is a free space inode the thread has not acquired the ordered
531+
* extents lockdep map.
532+
*/
533+
freespace_inode = btrfs_is_free_space_inode(btrfs_inode);
527534

528535
btrfs_lockdep_acquire(fs_info, btrfs_trans_pending_ordered);
529536
/* This is paired with btrfs_add_ordered_extent. */
@@ -597,6 +604,8 @@ void btrfs_remove_ordered_extent(struct btrfs_inode *btrfs_inode,
597604
}
598605
spin_unlock(&root->ordered_extent_lock);
599606
wake_up(&entry->wait);
607+
if (!freespace_inode)
608+
btrfs_lockdep_release(fs_info, btrfs_ordered_extent);
600609
}
601610

602611
static void btrfs_run_ordered_extent_work(struct btrfs_work *work)
@@ -715,9 +724,16 @@ void btrfs_start_ordered_extent(struct btrfs_ordered_extent *entry, int wait)
715724
u64 start = entry->file_offset;
716725
u64 end = start + entry->num_bytes - 1;
717726
struct btrfs_inode *inode = BTRFS_I(entry->inode);
727+
bool freespace_inode;
718728

719729
trace_btrfs_ordered_extent_start(inode, entry);
720730

731+
/*
732+
* If this is a free space inode do not take the ordered extents lockdep
733+
* map.
734+
*/
735+
freespace_inode = btrfs_is_free_space_inode(inode);
736+
721737
/*
722738
* pages in the range can be dirty, clean or writeback. We
723739
* start IO on any dirty ones so the wait doesn't stall waiting
@@ -726,6 +742,8 @@ void btrfs_start_ordered_extent(struct btrfs_ordered_extent *entry, int wait)
726742
if (!test_bit(BTRFS_ORDERED_DIRECT, &entry->flags))
727743
filemap_fdatawrite_range(inode->vfs_inode.i_mapping, start, end);
728744
if (wait) {
745+
if (!freespace_inode)
746+
btrfs_might_wait_for_event(inode->root->fs_info, btrfs_ordered_extent);
729747
wait_event(entry->wait, test_bit(BTRFS_ORDERED_COMPLETE,
730748
&entry->flags));
731749
}

0 commit comments

Comments
 (0)