--- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -685,6 +685,7 @@ struct extent_tree_info { struct mutex extent_tree_lock; /* locking extent radix tree */ struct list_head extent_list; /* lru list for shrinker */ spinlock_t extent_lock; /* locking extent lru list */ + spinlock_t et_read_lock; /* locking read extent tree */ atomic_t total_ext_tree; /* extent tree count */ struct list_head zombie_list; /* extent zombie tree list */ atomic_t total_zombie_tree; /* extent zombie tree count */ --- a/fs/f2fs/extent_cache.c +++ b/fs/f2fs/extent_cache.c @@ -675,13 +675,17 @@ static void __update_extent_tree_range(struct inode *inode, struct extent_node *prev_en = NULL, *next_en = NULL; struct extent_info ei, dei, prev; struct rb_node **insert_p = NULL, *insert_parent = NULL; + struct extent_tree_info *eti = &sbi->extent_tree[type]; unsigned int fofs = tei->fofs, len = tei->len; unsigned int end = fofs + len; bool updated = false; bool leftmost = false; - if (!et) + spin_lock(&eti->et_read_lock); + if (!et) { + spin_unlock(&eti->et_read_lock); return; + } if (type == EX_READ) trace_f2fs_update_read_extent_tree_range(inode, fofs, len, @@ -695,6 +699,7 @@ static void __update_extent_tree_range(struct inode *inode, if (type == EX_READ) { if (is_inode_flag_set(inode, FI_NO_EXTENT)) { write_unlock(&et->lock); + spin_unlock(&eti->et_read_lock); return; } @@ -824,6 +829,7 @@ static void __update_extent_tree_range(struct inode *inode, insert_p, insert_parent, leftmost); out_read_extent_cache: write_unlock(&et->lock); + spin_unlock(&eti->et_read_lock); if (updated) f2fs_mark_inode_dirty_sync(inode, true); @@ -1190,7 +1196,9 @@ static void __destroy_extent_tree(struct inode *inode, enum extent_type type) mutex_lock(&eti->extent_tree_lock); f2fs_bug_on(sbi, atomic_read(&et->node_cnt)); radix_tree_delete(&eti->extent_tree_root, inode->i_ino); + spin_lock(&eti->et_read_lock); kmem_cache_free(extent_tree_slab, et); + spin_unlock(&eti->et_read_lock); atomic_dec(&eti->total_ext_tree); mutex_unlock(&eti->extent_tree_lock); @@ -1211,6 +1219,7 @@ static void __init_extent_tree_info(struct extent_tree_info *eti) mutex_init(&eti->extent_tree_lock); INIT_LIST_HEAD(&eti->extent_list); spin_lock_init(&eti->extent_lock); + spin_lock_init(&eti->et_read_lock); atomic_set(&eti->total_ext_tree, 0); INIT_LIST_HEAD(&eti->zombie_list); atomic_set(&eti->total_zombie_tree, 0);