Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3159f943 authored by Matthew Wilcox's avatar Matthew Wilcox
Browse files

xarray: Replace exceptional entries



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: default avatarMatthew Wilcox <willy@infradead.org>
Reviewed-by: default avatarJosef Bacik <jbacik@fb.com>
parent 66ee620f
Loading
Loading
Loading
Loading
+1 −3
Original line number Diff line number Diff line
@@ -723,9 +723,7 @@ static inline bool pte_user(pte_t pte)
	BUILD_BUG_ON(_PAGE_HPTEFLAGS & (0x1f << _PAGE_BIT_SWAP_TYPE)); \
	BUILD_BUG_ON(_PAGE_HPTEFLAGS & _PAGE_SWP_SOFT_DIRTY);	\
	} while (0)
/*
 * on pte we don't need handle RADIX_TREE_EXCEPTIONAL_SHIFT;
 */

#define SWP_TYPE_BITS 5
#define __swp_type(x)		(((x).val >> _PAGE_BIT_SWAP_TYPE) \
				& ((1UL << SWP_TYPE_BITS) - 1))
+1 −3
Original line number Diff line number Diff line
@@ -313,9 +313,7 @@ static inline void __ptep_set_access_flags(struct vm_area_struct *vma,
#define MAX_SWAPFILES_CHECK() do { \
	BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > SWP_TYPE_BITS); \
	} while (0)
/*
 * on pte we don't need handle RADIX_TREE_EXCEPTIONAL_SHIFT;
 */

#define SWP_TYPE_BITS 5
#define __swp_type(x)		(((x).val >> _PAGE_BIT_SWAP_TYPE) \
				& ((1UL << SWP_TYPE_BITS) - 1))
+7 −10
Original line number Diff line number Diff line
@@ -5996,7 +5996,8 @@ i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
	count = __sg_page_count(sg);

	while (idx + count <= n) {
		unsigned long exception, i;
		void *entry;
		unsigned long i;
		int ret;

		/* If we cannot allocate and insert this entry, or the
@@ -6011,12 +6012,9 @@ i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
		if (ret && ret != -EEXIST)
			goto scan;

		exception =
			RADIX_TREE_EXCEPTIONAL_ENTRY |
			idx << RADIX_TREE_EXCEPTIONAL_SHIFT;
		entry = xa_mk_value(idx);
		for (i = 1; i < count; i++) {
			ret = radix_tree_insert(&iter->radix, idx + i,
						(void *)exception);
			ret = radix_tree_insert(&iter->radix, idx + i, entry);
			if (ret && ret != -EEXIST)
				goto scan;
		}
@@ -6054,15 +6052,14 @@ i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
	GEM_BUG_ON(!sg);

	/* If this index is in the middle of multi-page sg entry,
	 * the radixtree will contain an exceptional entry that points
	 * the radix tree will contain a value entry that points
	 * to the start of that range. We will return the pointer to
	 * the base page and the offset of this page within the
	 * sg entry's range.
	 */
	*offset = 0;
	if (unlikely(radix_tree_exception(sg))) {
		unsigned long base =
			(unsigned long)sg >> RADIX_TREE_EXCEPTIONAL_SHIFT;
	if (unlikely(xa_is_value(sg))) {
		unsigned long base = xa_to_value(sg);

		sg = radix_tree_lookup(&iter->radix, base);
		GEM_BUG_ON(!sg);
+6 −12
Original line number Diff line number Diff line
@@ -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);
+1 −1
Original line number Diff line number Diff line
@@ -440,7 +440,7 @@ static noinline int add_ra_bio_pages(struct inode *inode,
		rcu_read_lock();
		page = radix_tree_lookup(&mapping->i_pages, pg_index);
		rcu_read_unlock();
		if (page && !radix_tree_exceptional_entry(page)) {
		if (page && !xa_is_value(page)) {
			misses++;
			if (misses > 4)
				break;
Loading