ping? Is these two patches can be merged into linux-4.19? :'( Thanks, Gao Xiang On 2019/2/26 20:43, Gao Xiang wrote: > Hi Matthew, > > On 2019/2/26 13:14, Gao Xiang wrote: >> From: Matthew Wilcox <willy@xxxxxxxxxxxxx> >> >> commit 3159f943aafdbacb2f94c38fdaadabf2bbde2a14 upstream. >> >> Introduce xarray value entries and tagged pointers to replace radix >> tree exceptional entries. This is a slight change in encoding to allow >> the use of an extra bit (we can now store BITS_PER_LONG - 1 bits in a >> value entry). It is also a change in emphasis; exceptional entries are >> intimidating and different. As the comment explains, you can choose >> to store values or pointers in the xarray and they are both first-class >> citizens. >> >> Signed-off-by: Matthew Wilcox <willy@xxxxxxxxxxxxx> >> Reviewed-by: Josef Bacik <jbacik@xxxxxx> >> [ take the minimum subset of tagged pointer support only. ] >> Cc: Matthew Wilcox <willy@xxxxxxxxxxxxx> >> Signed-off-by: Gao Xiang <gaoxiang25@xxxxxxxxxx> >> --- >> change log v2: >> - fix tagged pointer apis to make it work properly pointed out by Matthew; > > Is this version ok? Could you kindly give an "Acked-by" tag for this patch? > > The following patch is important for erofs, I'd like to backport it ASAP... > staging: erofs: fix race when the managed cache is enabled > > It will be of great help. Thanks in advance! > > Thanks, > Gao Xiang > >> >> drivers/staging/erofs/utils.c | 18 +++++---------- >> include/linux/xarray.h | 52 +++++++++++++++++++++++++++++++++++++++++++ >> 2 files changed, 58 insertions(+), 12 deletions(-) >> >> diff --git a/drivers/staging/erofs/utils.c b/drivers/staging/erofs/utils.c >> index 595cf90af9bb..bdee9bd09f11 100644 >> --- a/drivers/staging/erofs/utils.c >> +++ b/drivers/staging/erofs/utils.c >> @@ -35,7 +35,6 @@ static atomic_long_t erofs_global_shrink_cnt; >> >> #ifdef CONFIG_EROFS_FS_ZIP >> >> -/* radix_tree and the future XArray both don't use tagptr_t yet */ >> struct erofs_workgroup *erofs_find_workgroup( >> struct super_block *sb, pgoff_t index, bool *tag) >> { >> @@ -47,9 +46,8 @@ struct erofs_workgroup *erofs_find_workgroup( >> rcu_read_lock(); >> grp = radix_tree_lookup(&sbi->workstn_tree, index); >> if (grp != NULL) { >> - *tag = radix_tree_exceptional_entry(grp); >> - grp = (void *)((unsigned long)grp & >> - ~RADIX_TREE_EXCEPTIONAL_ENTRY); >> + *tag = xa_pointer_tag(grp); >> + grp = xa_untag_pointer(grp); >> >> if (erofs_workgroup_get(grp, &oldcount)) { >> /* prefer to relax rcu read side */ >> @@ -83,9 +81,7 @@ int erofs_register_workgroup(struct super_block *sb, >> sbi = EROFS_SB(sb); >> erofs_workstn_lock(sbi); >> >> - if (tag) >> - grp = (void *)((unsigned long)grp | >> - 1UL << RADIX_TREE_EXCEPTIONAL_SHIFT); >> + grp = xa_tag_pointer(grp, tag); >> >> err = radix_tree_insert(&sbi->workstn_tree, >> grp->index, grp); >> @@ -131,9 +127,7 @@ unsigned long erofs_shrink_workstation(struct erofs_sb_info *sbi, >> >> for (i = 0; i < found; ++i) { >> int cnt; >> - struct erofs_workgroup *grp = (void *) >> - ((unsigned long)batch[i] & >> - ~RADIX_TREE_EXCEPTIONAL_ENTRY); >> + struct erofs_workgroup *grp = xa_untag_pointer(batch[i]); >> >> first_index = grp->index + 1; >> >> @@ -150,8 +144,8 @@ unsigned long erofs_shrink_workstation(struct erofs_sb_info *sbi, >> #endif >> continue; >> >> - if (radix_tree_delete(&sbi->workstn_tree, >> - grp->index) != grp) { >> + if (xa_untag_pointer(radix_tree_delete(&sbi->workstn_tree, >> + grp->index)) != grp) { >> #ifdef EROFS_FS_HAS_MANAGED_CACHE >> skip: >> erofs_workgroup_unfreeze(grp, 1); >> diff --git a/include/linux/xarray.h b/include/linux/xarray.h >> index 2dfc8006fe64..51ae9779d08b 100644 >> --- a/include/linux/xarray.h >> +++ b/include/linux/xarray.h >> @@ -9,6 +9,58 @@ >> >> #include <linux/spinlock.h> >> >> +/** >> + * xa_tag_pointer() - Create an XArray entry for a tagged pointer. >> + * @p: Plain pointer. >> + * @tag: Tag value (0 or 1). >> + * >> + * If the user of the XArray prefers, they can tag their pointers instead >> + * of storing value entries. Two tags are available (0 and 1). >> + * These are distinct from the xa_mark_t as they are not replicated up >> + * through the array and cannot be searched for. >> + * >> + * Context: Any context. >> + * Return: An XArray entry. >> + */ >> +static inline void *xa_tag_pointer(void *p, unsigned long tag) >> +{ >> + if (__builtin_constant_p(tag)) >> + BUILD_BUG_ON(tag > 1); >> + else >> + BUG_ON(tag > 1); >> + return (void *)((unsigned long)p | (tag << 1)); >> +} >> + >> +/** >> + * xa_untag_pointer() - Turn an XArray entry into a plain pointer. >> + * @entry: XArray entry. >> + * >> + * If you have stored a tagged pointer in the XArray, call this function >> + * to get the untagged version of the pointer. >> + * >> + * Context: Any context. >> + * Return: A pointer. >> + */ >> +static inline void *xa_untag_pointer(void *entry) >> +{ >> + return (void *)((unsigned long)entry & ~3UL); >> +} >> + >> +/** >> + * xa_pointer_tag() - Get the tag stored in an XArray entry. >> + * @entry: XArray entry. >> + * >> + * If you have stored a tagged pointer in the XArray, call this function >> + * to get the tag of that pointer. >> + * >> + * Context: Any context. >> + * Return: A tag. >> + */ >> +static inline unsigned int xa_pointer_tag(void *entry) >> +{ >> + return ((unsigned long)entry & 3UL) >> 1; >> +} >> + >> #define xa_trylock(xa) spin_trylock(&(xa)->xa_lock) >> #define xa_lock(xa) spin_lock(&(xa)->xa_lock) >> #define xa_unlock(xa) spin_unlock(&(xa)->xa_lock) >>