--- a/fs/f2fs/extent_cache.c +++ b/fs/f2fs/extent_cache.c @@ -675,6 +675,7 @@ 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; @@ -690,11 +691,13 @@ static void __update_extent_tree_range(struct inode *inode, trace_f2fs_update_age_extent_tree_range(inode, fofs, len, tei->age, tei->last_blocks); + spin_lock(&eti->et_read_lock); write_lock(&et->lock); 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 +827,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 +1194,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 +1217,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); --- 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 */