From: Matthew Wilcox Date: Thu, 18 Oct 2018 19:36:42 +0000 (-0400) Subject: erofs: Convert workstn_tree to XArray X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=839c0669fd2aef830fb8701da8663bf218cddd80;p=users%2Fwilly%2Fxarray.git erofs: Convert workstn_tree to XArray Rename it to compression_work as a better reflection of what it's for. Signed-off-by: Matthew Wilcox --- diff --git a/drivers/staging/erofs/internal.h b/drivers/staging/erofs/internal.h index 963cc1b8b8961..ca16abca8598c 100644 --- a/drivers/staging/erofs/internal.h +++ b/drivers/staging/erofs/internal.h @@ -93,8 +93,7 @@ struct erofs_sb_info { /* cluster size in bit shift */ unsigned char clusterbits; - /* the dedicated workstation for compression */ - struct radix_tree_root workstn_tree; + struct xarray compression_work; /* threshold for decompression synchronously */ unsigned int max_sync_decompress_pages; @@ -183,8 +182,6 @@ static inline void *erofs_kmalloc(struct erofs_sb_info *sbi, #define test_opt(sbi, option) ((sbi)->mount_opt & EROFS_MOUNT_##option) #ifdef CONFIG_EROFS_FS_ZIP -#define erofs_workstn_lock(sbi) xa_lock(&(sbi)->workstn_tree) -#define erofs_workstn_unlock(sbi) xa_unlock(&(sbi)->workstn_tree) /* basic unit of the workstation of a super_block */ struct erofs_workgroup { diff --git a/drivers/staging/erofs/super.c b/drivers/staging/erofs/super.c index 54494412eba41..f9964d40aed32 100644 --- a/drivers/staging/erofs/super.c +++ b/drivers/staging/erofs/super.c @@ -421,7 +421,7 @@ static int erofs_read_super(struct super_block *sb, sb->s_flags &= ~SB_POSIXACL; #ifdef CONFIG_EROFS_FS_ZIP - INIT_RADIX_TREE(&sbi->workstn_tree, GFP_ATOMIC); + xa_init(&sbi->compression_work); #endif #ifdef EROFS_FS_HAS_MANAGED_CACHE diff --git a/drivers/staging/erofs/utils.c b/drivers/staging/erofs/utils.c index 4bbd3bf34acd9..9e9163a2bd777 100644 --- a/drivers/staging/erofs/utils.c +++ b/drivers/staging/erofs/utils.c @@ -72,7 +72,7 @@ struct erofs_workgroup *erofs_find_workgroup(struct super_block *sb, repeat: rcu_read_lock(); - grp = radix_tree_lookup(&sbi->workstn_tree, index); + grp = xa_load(&sbi->compression_work, index); if (grp) { *tag = xa_pointer_tag(grp); grp = xa_untag_pointer(grp); @@ -102,24 +102,17 @@ int erofs_register_workgroup(struct super_block *sb, return -EINVAL; } - err = radix_tree_preload(GFP_NOFS); - if (err) - return err; - sbi = EROFS_SB(sb); - erofs_workstn_lock(sbi); - - grp = xa_tag_pointer(grp, tag); /* * Bump up reference count before making this workgroup * visible to other users in order to avoid potential UAF - * without serialized by erofs_workstn_lock. + * without serialized by xa_lock. */ __erofs_workgroup_get(grp); - err = radix_tree_insert(&sbi->workstn_tree, - grp->index, grp); + err = xa_insert(&sbi->compression_work, grp->index, + xa_tag_pointer(grp, tag), GFP_KERNEL); if (unlikely(err)) /* * it's safe to decrease since the workgroup isn't visible @@ -127,8 +120,6 @@ int erofs_register_workgroup(struct super_block *sb, */ __erofs_workgroup_put(grp); - erofs_workstn_unlock(sbi); - radix_tree_preload_end(); return err; } @@ -171,7 +162,7 @@ static bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi, /* * note that all cached pages should be unlinked - * before delete it from the radix tree. + * before delete it from the xarray. * Otherwise some cached pages of an orphan old workgroup * could be still linked after the new one is available. */ @@ -185,7 +176,7 @@ static bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi, * however in order to avoid some race conditions, add a * DBG_BUGON to observe this in advance. */ - DBG_BUGON(xa_untag_pointer(radix_tree_delete(&sbi->workstn_tree, + DBG_BUGON(xa_untag_pointer(xa_erase(&sbi->compression_work, grp->index)) != grp); /* @@ -210,7 +201,7 @@ static bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi, if (cnt > 1) return false; - DBG_BUGON(xa_untag_pointer(radix_tree_delete(&sbi->workstn_tree, + DBG_BUGON(xa_untag_pointer(xa_erase(&sbi->compression_work, grp->index)) != grp); /* (rarely) could be grabbed again when freeing */ @@ -224,21 +215,12 @@ unsigned long erofs_shrink_workstation(struct erofs_sb_info *sbi, unsigned long nr_shrink, bool cleanup) { - pgoff_t first_index = 0; - void *batch[PAGEVEC_SIZE]; + struct erofs_workgroup *grp; unsigned int freed = 0; + unsigned long index; - int i, found; -repeat: - erofs_workstn_lock(sbi); - - found = radix_tree_gang_lookup(&sbi->workstn_tree, - batch, first_index, PAGEVEC_SIZE); - - for (i = 0; i < found; ++i) { - struct erofs_workgroup *grp = xa_untag_pointer(batch[i]); - - first_index = grp->index + 1; + xa_for_each(&sbi->compression_work, index, grp) { + grp = xa_untag_pointer(grp); /* try to shrink each valid workgroup */ if (!erofs_try_to_release_workgroup(sbi, grp, cleanup)) @@ -248,10 +230,7 @@ repeat: if (unlikely(!--nr_shrink)) break; } - erofs_workstn_unlock(sbi); - if (i && nr_shrink) - goto repeat; return freed; }