From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6BA14C54798 for ; Sat, 2 Mar 2024 21:32:56 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 8155D94000D; Sat, 2 Mar 2024 16:32:55 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 7C69C940007; Sat, 2 Mar 2024 16:32:55 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 6668794000D; Sat, 2 Mar 2024 16:32:55 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0011.hostedemail.com [216.40.44.11]) by kanga.kvack.org (Postfix) with ESMTP id 56824940007 for ; Sat, 2 Mar 2024 16:32:55 -0500 (EST) Received: from smtpin20.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay04.hostedemail.com (Postfix) with ESMTP id D85391A0307 for ; Sat, 2 Mar 2024 21:32:54 +0000 (UTC) X-FDA: 81853399068.20.1BE0B7E Received: from sin.source.kernel.org (sin.source.kernel.org [145.40.73.55]) by imf23.hostedemail.com (Postfix) with ESMTP id 41DBE140006 for ; Sat, 2 Mar 2024 21:32:51 +0000 (UTC) Authentication-Results: imf23.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=o7ghApHX; dmarc=pass (policy=none) header.from=kernel.org; spf=pass (imf23.hostedemail.com: domain of chrisl@kernel.org designates 145.40.73.55 as permitted sender) smtp.mailfrom=chrisl@kernel.org ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1709415173; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=OBPdryyTZkchW1+ktM2l6FKS5r2HmBKf3W7nF6qqAJo=; b=UmJQXTEa5oVIeq4+OAoJfLkQhLEX9Q3HV0Ya1pqlhX+D+/AgzbIjKW/R0+au6ccWYahAfP RvzkzBZ1iskVjhRCcJDiOG9gUl82yDY7YqPUfoEdOvkkeTh/yiKoYFzRKvORlr0mSBqFbD o6vHokEoaO04/cwjOt2el8Uwb8GE6Yk= ARC-Authentication-Results: i=1; imf23.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=o7ghApHX; dmarc=pass (policy=none) header.from=kernel.org; spf=pass (imf23.hostedemail.com: domain of chrisl@kernel.org designates 145.40.73.55 as permitted sender) smtp.mailfrom=chrisl@kernel.org ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1709415173; a=rsa-sha256; cv=none; b=Szfu0WqNnuNYIJfLo9ViPVfh1NhpeDo4iMIFP1+S1lQGKEyvPcvaxH/MjSa4NvCERt8iL7 RTmbam4cvBs5SdA28mmB2wWTLV533foNGl4tUvKeNAqH+bUzMgfF2n961A5ufSOy5zBt5l V6WI7UhYUwTlzP6ooT7dI6lVz3g4/xw= Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by sin.source.kernel.org (Postfix) with ESMTP id 73647CE0D9B for ; Sat, 2 Mar 2024 21:32:47 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id A2A23C43390 for ; Sat, 2 Mar 2024 21:32:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1709415166; bh=Vy82TysZvTReEs/sWmhkLGHVDSuhML4G+RW5tpxD4N8=; h=References:In-Reply-To:From:Date:Subject:To:Cc:From; b=o7ghApHXA/dTHA0SS0GQW9YkYzvvGMT6fBdGZD9wCcHHXzz0ge3Y8RhK+Mvv0Mtfz y7qj2ioBEW7Uo5lFB7q2/C5H9t38dK65e2/PtBNQ8x05CtemHDQujbjR8wNB1zdFId 6lk6nYzhxsqIM5eiZNRlE0S1wP6KOg4dfZfiIR0FSU2dDltGuhoBLpeEW41wy/2HJx fzDA8y2M+rmSU4+SAMYbfeWLJ1pa+bMv7UP4rkGDN70hkAkHXdfOtwVQboBCL7/XwQ tpCkFRT+r8ywztZIfmE3XyChJtZSxjuGrxUOqfIBZwvpH3dwMeyC29Dz9BpEDsU1qi 7qxi3713ECVcw== Received: by mail-il1-f169.google.com with SMTP id e9e14a558f8ab-365b3d92354so19657765ab.1 for ; Sat, 02 Mar 2024 13:32:46 -0800 (PST) X-Forwarded-Encrypted: i=1; AJvYcCUTLazTwYtysN5XqnMdZJrDyQgOjN2BYTT9p2ZovO02DUffR4MhFTOlSmOTAOom/dAQfgflpYT/vkpnqg6jTqO7TEY= X-Gm-Message-State: AOJu0YxB1gpVPTOe1l+Osvtt812xLUri8RZpV8L2FZ5BCyHoPcnC0+5q VPSnKJnbJUBkgQzXEQbn/Buqwr7danoc6Z0lEGYcK1RTEdxEUzvTS5DxnPTiNpN+j5t36S7Pbhq YhrqYlqR0zKH+8te8aRXxnCIo1fJuIVU+OORp X-Google-Smtp-Source: AGHT+IHTYJqFl0v9Tk4EiXZf0kUsVkbMeGy3r83TMvsiekelZ0vRgDFWVcvKs6XdqWnpau0TBQW7jS+UWtke/Q2CFBY= X-Received: by 2002:a05:6e02:1c0f:b0:365:1158:2822 with SMTP id l15-20020a056e021c0f00b0036511582822mr6673518ilh.0.1709415165862; Sat, 02 Mar 2024 13:32:45 -0800 (PST) MIME-Version: 1.0 References: <20240302-zswap-xarray-v3-1-5900252f2302@kernel.org> In-Reply-To: <20240302-zswap-xarray-v3-1-5900252f2302@kernel.org> From: Chris Li Date: Sat, 2 Mar 2024 13:32:33 -0800 X-Gmail-Original-Message-ID: Message-ID: Subject: Re: [PATCH v3] zswap: replace RB tree with xarray To: Andrew Morton Cc: linux-kernel@vger.kernel.org, linux-mm@kvack.org, Yosry Ahmed , Nhat Pham , Johannes Weiner , "Matthew Wilcox (Oracle)" , Chengming Zhou , Barry Song Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Rspamd-Queue-Id: 41DBE140006 X-Rspam-User: X-Rspamd-Server: rspam04 X-Stat-Signature: h1bgiawrscgydks5h5adaj13fnxk1ism X-HE-Tag: 1709415171-930685 X-HE-Meta: U2FsdGVkX19A+g8VpAM9+b0FTWSImM/m5KuVU8cdKhw73gV8+/IoqEezc0cKNpg+uy0WEVp1USHGIDL/2LILXunOb5PRMuDblmW0djrEr8urkm/mK6rpWgHEBqEgfl3O6sKBO4m+PgALAK/k6Lp94GG+bDnhzWrHUdwczBLjQcY1IsmNigqRmDAdsuPqnFEIWI4V4kFeksrpLEodpemrc6mb+Pt344uhT4bc8GdJkDDyjxnjyoBnn5DN5oSN6SIdPZXI5ZoRUZIHoTgXwrTYTADasUvaQ+466G8+9ISq2Re1sz6gY4eNjGsw+l2lqLzdHBv/lg6hJl4K6pQtL8rK5akRTHCBVechHvvgJ+Iw1w/xFsSBL1I21S7KSjOuycoydh2qTgjHbY4Bb4FrZ1F7c6goSxVu0GLUEQPOeGSU8UhdMwJYjqGnKj65muLYaZClN3wWECPbKacwZDPYqQXebT5ea8rOOw+NZRoJEKEoH1ZTEhZysj+Ok/lW59WmtUROqVMEH2c/Oemo1wstgcZj0tbnr/j/tpyqNVs+NH5H+mVEaJBtbjKuqVlFm5YqqMARKbAGKF7aexEQfbXzuHIQ7jHtA9UZ9s1fsbRDPDLLOfXZu04Jm4qaNZ76Sgu0OcbI5ahchZFOjUc9HMOVZ/GBm2Dpwcim9cRgp+jXQBCzWfq8IBUZttDTbWY2y1Pe7EGgFmG2VxF1GP/t3hcBR7UAOQfb+iIuTq+MKFdjSpblUKGD0gouJYshpk/ixFE+sD461cKW5YBFrzPgwzsQBRCQhnZHTviUuL7ykZzrcgZHtMYJz+fjdk/xajA/X7TRwhcxAiWqtbUFqhi6zAi38i97xiCEMec6YwNunaVo/c7Hsnpeeadk9n92kDhH3g8AYKTpdsxbFgHcN0GYfaDv/NtjjZDX0FVbBhAgschOByVOplWpaEVSTSQ/we6vXbX8WFe7NRbsmW0wR4qIK1nWFL1 LBxs2/3N 7flQ0nY22Ies6eMrKHzzQ0276DkmwUyOpjKjzvykn+ZAfMDDpmzE3neFK7hWYL1KoTfpyIULfTJVKJlhd0DUwX/RsDXhGyE6STkqcOSIjyWtIX1Zlb6Xp5LeRP2Nwlvbds0BHHc1JHz2gF3OxdFFIOO8HitbTp/XEdhlg3GktjyLxeFjZrm7zuiygXAfqzdImn9FAp+x7pdpQTiOFRDGvymO56nvNQv7PDQHeQfGsnqkkBhUOFQzKIQLmRIhq5wJo3HCgTmJdtLXRZZRDwBNeee5+Dg== X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: I have finally set up my own kernel compile machine. My home test machine is slower and has less cores(12). The kernel compile test is based on Chengming's test script with minor modification to do loops. Run the kernel build testing 10 times for each version, averages: (memory.max=3D2GB, zswap shrinker and writeback enabled, one 50GB swapfile.= ) mm-9a0181a3710eb xarray v3 user 3526.829 3526.842 sys 532.754 524.310 real 198.748 198.206 So there is about 1.5% improvement on sys time according to my test. Chris On Sat, Mar 2, 2024 at 12:16=E2=80=AFPM Chris Li wrote: > > Very deep RB tree requires rebalance at times. That > contributes to the zswap fault latencies. Xarray does not > need to perform tree rebalance. Replacing RB tree to xarray > can have some small performance gain. > > One small difference is that xarray insert might fail with > ENOMEM, while RB tree insert does not allocate additional > memory. > > The zswap_entry size will reduce a bit due to removing the > RB node, which has two pointers and a color field. Xarray > store the pointer in the xarray tree rather than the > zswap_entry. Every entry has one pointer from the xarray > tree. Overall, switching to xarray should save some memory, > if the swap entries are densely packed. > > Notice the zswap_rb_search and zswap_rb_insert always > followed by zswap_rb_erase. Fold the entry erase into > zswap_xa_search_and_erase and zswap_xa_insert. That saves > one tree lookup as well. > > Remove zswap_invalidate_entry due to no need to call > zswap_rb_erase any more. Use zswap_free_entry instead. > > The "struct zswap_tree" has been replaced by "struct xarray". > The tree spin lock has transferred to the xarray lock. > > --- > > > Signed-off-by: Chris Li > --- > Changes in v3: > - Use xa_cmpxchg instead of zswap_xa_search_and_delete in zswap_writeback= _entry. > - Use xa_store in zswap_xa_insert directly. Reduce the scope of spinlock. > - Fix xa_store error handling for same page fill case. > - Link to v2: https://lore.kernel.org/r/20240229-zswap-xarray-v2-1-e50284= dfcdb1@kernel.org > > Changes in v2: > - Replace struct zswap_tree with struct xarray. > - Remove zswap_tree spinlock, use xarray lock instead. > - Fold zswap_rb_erase() into zswap_xa_search_and_delete() and zswap_xa_in= sert(). > - Delete zswap_invalidate_entry(), use zswap_free_entry() instead. > - Link to v1: https://lore.kernel.org/r/20240117-zswap-xarray-v1-0-6daa86= c08fae@kernel.org > --- > mm/zswap.c | 174 +++++++++++++++++++++++--------------------------------= ------ > 1 file changed, 64 insertions(+), 110 deletions(-) > > diff --git a/mm/zswap.c b/mm/zswap.c > index 011e068eb355..9d0bfe077ff1 100644 > --- a/mm/zswap.c > +++ b/mm/zswap.c > @@ -20,7 +20,6 @@ > #include > #include > #include > -#include > #include > #include > #include > @@ -71,6 +70,8 @@ static u64 zswap_reject_compress_poor; > static u64 zswap_reject_alloc_fail; > /* Store failed because the entry metadata could not be allocated (rare)= */ > static u64 zswap_reject_kmemcache_fail; > +/* Store failed because xarray can't insert the entry*/ > +static u64 zswap_reject_xarray_fail; > > /* Shrinker work queue */ > static struct workqueue_struct *shrink_wq; > @@ -196,7 +197,6 @@ static struct { > * This structure contains the metadata for tracking a single compressed > * page within zswap. > * > - * rbnode - links the entry into red-black tree for the appropriate swap= type > * swpentry - associated swap entry, the offset indexes into the red-bla= ck tree > * length - the length in bytes of the compressed page data. Needed dur= ing > * decompression. For a same value filled page length is 0, and= both > @@ -208,7 +208,6 @@ static struct { > * lru - handle to the pool's lru used to evict pages. > */ > struct zswap_entry { > - struct rb_node rbnode; > swp_entry_t swpentry; > unsigned int length; > struct zswap_pool *pool; > @@ -220,12 +219,7 @@ struct zswap_entry { > struct list_head lru; > }; > > -struct zswap_tree { > - struct rb_root rbroot; > - spinlock_t lock; > -}; > - > -static struct zswap_tree *zswap_trees[MAX_SWAPFILES]; > +static struct xarray *zswap_trees[MAX_SWAPFILES]; > static unsigned int nr_zswap_trees[MAX_SWAPFILES]; > > /* RCU-protected iteration */ > @@ -253,10 +247,10 @@ static bool zswap_has_pool; > * helpers and fwd declarations > **********************************/ > > -static inline struct zswap_tree *swap_zswap_tree(swp_entry_t swp) > +static inline struct xarray *swap_zswap_tree(swp_entry_t swp) > { > - return &zswap_trees[swp_type(swp)][swp_offset(swp) > - >> SWAP_ADDRESS_SPACE_SHIFT]; > + return zswap_trees[swp_type(swp)] + (swp_offset(swp) > + >> SWAP_ADDRESS_SPACE_SHIFT); > } > > #define zswap_pool_debug(msg, p) \ > @@ -805,60 +799,37 @@ void zswap_memcg_offline_cleanup(struct mem_cgroup = *memcg) > } > > /********************************* > -* rbtree functions > +* xarray functions > **********************************/ > -static struct zswap_entry *zswap_rb_search(struct rb_root *root, pgoff_t= offset) > +static struct zswap_entry *zswap_xa_search_and_erase(struct xarray *tree= , pgoff_t offset) > { > - struct rb_node *node =3D root->rb_node; > - struct zswap_entry *entry; > - pgoff_t entry_offset; > - > - while (node) { > - entry =3D rb_entry(node, struct zswap_entry, rbnode); > - entry_offset =3D swp_offset(entry->swpentry); > - if (entry_offset > offset) > - node =3D node->rb_left; > - else if (entry_offset < offset) > - node =3D node->rb_right; > - else > - return entry; > - } > - return NULL; > + return xa_erase(tree, offset); > } > > /* > * In the case that a entry with the same offset is found, a pointer to > - * the existing entry is stored in dupentry and the function returns -EE= XIST > + * the existing entry is stored in old and erased from the tree. > + * Function return error on insert. > */ > -static int zswap_rb_insert(struct rb_root *root, struct zswap_entry *ent= ry, > - struct zswap_entry **dupentry) > +static int zswap_xa_insert(struct xarray *tree, struct zswap_entry *entr= y, > + struct zswap_entry **old) > { > - struct rb_node **link =3D &root->rb_node, *parent =3D NULL; > - struct zswap_entry *myentry; > - pgoff_t myentry_offset, entry_offset =3D swp_offset(entry->swpent= ry); > - > - while (*link) { > - parent =3D *link; > - myentry =3D rb_entry(parent, struct zswap_entry, rbnode); > - myentry_offset =3D swp_offset(myentry->swpentry); > - if (myentry_offset > entry_offset) > - link =3D &(*link)->rb_left; > - else if (myentry_offset < entry_offset) > - link =3D &(*link)->rb_right; > - else { > - *dupentry =3D myentry; > - return -EEXIST; > - } > - } > - rb_link_node(&entry->rbnode, parent, link); > - rb_insert_color(&entry->rbnode, root); > - return 0; > -} > + int err; > + struct zswap_entry *e; > + pgoff_t offset =3D swp_offset(entry->swpentry); > > -static void zswap_rb_erase(struct rb_root *root, struct zswap_entry *ent= ry) > -{ > - rb_erase(&entry->rbnode, root); > - RB_CLEAR_NODE(&entry->rbnode); > + e =3D xa_store(tree, offset, entry, GFP_KERNEL); > + err =3D xa_err(e); > + > + if (err) { > + e =3D xa_erase(tree, offset); > + if (err =3D=3D -ENOMEM) > + zswap_reject_alloc_fail++; > + else > + zswap_reject_xarray_fail++; > + } > + *old =3D e; > + return err; > } > > /********************************* > @@ -872,7 +843,6 @@ static struct zswap_entry *zswap_entry_cache_alloc(gf= p_t gfp, int nid) > entry =3D kmem_cache_alloc_node(zswap_entry_cache, gfp, nid); > if (!entry) > return NULL; > - RB_CLEAR_NODE(&entry->rbnode); > return entry; > } > > @@ -914,17 +884,6 @@ static void zswap_entry_free(struct zswap_entry *ent= ry) > zswap_update_total_size(); > } > > -/* > - * The caller hold the tree lock and search the entry from the tree, > - * so it must be on the tree, remove it from the tree and free it. > - */ > -static void zswap_invalidate_entry(struct zswap_tree *tree, > - struct zswap_entry *entry) > -{ > - zswap_rb_erase(&tree->rbroot, entry); > - zswap_entry_free(entry); > -} > - > /********************************* > * compressed storage functions > **********************************/ > @@ -1113,7 +1072,9 @@ static void zswap_decompress(struct zswap_entry *en= try, struct page *page) > static int zswap_writeback_entry(struct zswap_entry *entry, > swp_entry_t swpentry) > { > - struct zswap_tree *tree; > + struct xarray *tree; > + pgoff_t offset =3D swp_offset(swpentry); > + struct zswap_entry *e; > struct folio *folio; > struct mempolicy *mpol; > bool folio_was_allocated; > @@ -1150,19 +1111,14 @@ static int zswap_writeback_entry(struct zswap_ent= ry *entry, > * be dereferenced. > */ > tree =3D swap_zswap_tree(swpentry); > - spin_lock(&tree->lock); > - if (zswap_rb_search(&tree->rbroot, swp_offset(swpentry)) !=3D ent= ry) { > - spin_unlock(&tree->lock); > + e =3D xa_cmpxchg(tree, offset, entry, NULL, GFP_KERNEL); > + if (e !=3D entry) { > delete_from_swap_cache(folio); > folio_unlock(folio); > folio_put(folio); > return -ENOMEM; > } > > - /* Safe to deref entry after the entry is verified above. */ > - zswap_rb_erase(&tree->rbroot, entry); > - spin_unlock(&tree->lock); > - > zswap_decompress(entry, &folio->page); > > count_vm_event(ZSWPWB); > @@ -1471,10 +1427,11 @@ bool zswap_store(struct folio *folio) > { > swp_entry_t swp =3D folio->swap; > pgoff_t offset =3D swp_offset(swp); > - struct zswap_tree *tree =3D swap_zswap_tree(swp); > - struct zswap_entry *entry, *dupentry; > + struct xarray *tree =3D swap_zswap_tree(swp); > + struct zswap_entry *entry, *old; > struct obj_cgroup *objcg =3D NULL; > struct mem_cgroup *memcg =3D NULL; > + int err; > > VM_WARN_ON_ONCE(!folio_test_locked(folio)); > VM_WARN_ON_ONCE(!folio_test_swapcache(folio)); > @@ -1526,6 +1483,7 @@ bool zswap_store(struct folio *folio) > kunmap_local(src); > entry->length =3D 0; > entry->value =3D value; > + entry->pool =3D NULL; > atomic_inc(&zswap_same_filled_pages); > goto insert_entry; > } > @@ -1562,21 +1520,21 @@ bool zswap_store(struct folio *folio) > } > > /* map */ > - spin_lock(&tree->lock); > /* > * The folio may have been dirtied again, invalidate the > * possibly stale entry before inserting the new entry. > */ > - if (zswap_rb_insert(&tree->rbroot, entry, &dupentry) =3D=3D -EEXI= ST) { > - zswap_invalidate_entry(tree, dupentry); > - WARN_ON(zswap_rb_insert(&tree->rbroot, entry, &dupentry))= ; > - } > + err =3D zswap_xa_insert(tree, entry, &old); > + if (old) > + zswap_entry_free(old); > + if (err) > + goto insert_failed; > + > if (entry->length) { > INIT_LIST_HEAD(&entry->lru); > zswap_lru_add(&zswap.list_lru, entry); > atomic_inc(&zswap.nr_stored); > } > - spin_unlock(&tree->lock); > > /* update stats */ > atomic_inc(&zswap_stored_pages); > @@ -1585,6 +1543,12 @@ bool zswap_store(struct folio *folio) > > return true; > > +insert_failed: > + if (!entry->length) { > + atomic_dec(&zswap_same_filled_pages); > + goto freepage; > + } > + zpool_free(zswap_find_zpool(entry), entry->handle); > put_pool: > zswap_pool_put(entry->pool); > freepage: > @@ -1598,11 +1562,9 @@ bool zswap_store(struct folio *folio) > * possibly stale entry which was previously stored at this offse= t. > * Otherwise, writeback could overwrite the new data in the swapf= ile. > */ > - spin_lock(&tree->lock); > - entry =3D zswap_rb_search(&tree->rbroot, offset); > + entry =3D zswap_xa_search_and_erase(tree, offset); > if (entry) > - zswap_invalidate_entry(tree, entry); > - spin_unlock(&tree->lock); > + zswap_entry_free(entry); > return false; > > shrink: > @@ -1615,20 +1577,15 @@ bool zswap_load(struct folio *folio) > swp_entry_t swp =3D folio->swap; > pgoff_t offset =3D swp_offset(swp); > struct page *page =3D &folio->page; > - struct zswap_tree *tree =3D swap_zswap_tree(swp); > + struct xarray *tree =3D swap_zswap_tree(swp); > struct zswap_entry *entry; > u8 *dst; > > VM_WARN_ON_ONCE(!folio_test_locked(folio)); > > - spin_lock(&tree->lock); > - entry =3D zswap_rb_search(&tree->rbroot, offset); > - if (!entry) { > - spin_unlock(&tree->lock); > + entry =3D zswap_xa_search_and_erase(tree, offset); > + if (!entry) > return false; > - } > - zswap_rb_erase(&tree->rbroot, entry); > - spin_unlock(&tree->lock); > > if (entry->length) > zswap_decompress(entry, page); > @@ -1652,19 +1609,17 @@ bool zswap_load(struct folio *folio) > void zswap_invalidate(swp_entry_t swp) > { > pgoff_t offset =3D swp_offset(swp); > - struct zswap_tree *tree =3D swap_zswap_tree(swp); > + struct xarray *tree =3D swap_zswap_tree(swp); > struct zswap_entry *entry; > > - spin_lock(&tree->lock); > - entry =3D zswap_rb_search(&tree->rbroot, offset); > + entry =3D zswap_xa_search_and_erase(tree, offset); > if (entry) > - zswap_invalidate_entry(tree, entry); > - spin_unlock(&tree->lock); > + zswap_entry_free(entry); > } > > int zswap_swapon(int type, unsigned long nr_pages) > { > - struct zswap_tree *trees, *tree; > + struct xarray *trees, *tree; > unsigned int nr, i; > > nr =3D DIV_ROUND_UP(nr_pages, SWAP_ADDRESS_SPACE_PAGES); > @@ -1674,11 +1629,8 @@ int zswap_swapon(int type, unsigned long nr_pages) > return -ENOMEM; > } > > - for (i =3D 0; i < nr; i++) { > - tree =3D trees + i; > - tree->rbroot =3D RB_ROOT; > - spin_lock_init(&tree->lock); > - } > + for (i =3D 0; i < nr; i++) > + xa_init(trees + i); > > nr_zswap_trees[type] =3D nr; > zswap_trees[type] =3D trees; > @@ -1687,7 +1639,7 @@ int zswap_swapon(int type, unsigned long nr_pages) > > void zswap_swapoff(int type) > { > - struct zswap_tree *trees =3D zswap_trees[type]; > + struct xarray *trees =3D zswap_trees[type]; > unsigned int i; > > if (!trees) > @@ -1695,7 +1647,7 @@ void zswap_swapoff(int type) > > /* try_to_unuse() invalidated all the entries already */ > for (i =3D 0; i < nr_zswap_trees[type]; i++) > - WARN_ON_ONCE(!RB_EMPTY_ROOT(&trees[i].rbroot)); > + WARN_ON_ONCE(!xa_empty(trees + i)); > > kvfree(trees); > nr_zswap_trees[type] =3D 0; > @@ -1727,6 +1679,8 @@ static int zswap_debugfs_init(void) > zswap_debugfs_root, &zswap_reject_kmemcache_fa= il); > debugfs_create_u64("reject_compress_fail", 0444, > zswap_debugfs_root, &zswap_reject_compress_fai= l); > + debugfs_create_u64("reject_xarray_fail", 0444, > + zswap_debugfs_root, &zswap_reject_xarray_fail)= ; > debugfs_create_u64("reject_compress_poor", 0444, > zswap_debugfs_root, &zswap_reject_compress_poo= r); > debugfs_create_u64("written_back_pages", 0444, > > --- > base-commit: 9a0181a3710eba1f5c6d19eadcca888be3d54e4f > change-id: 20240104-zswap-xarray-716260e541e3 > > Best regards, > -- > Chris Li > >