From: Hyeonggon Yoo <42.hyeyoo@gmail.com>
To: lkp@lists.01.org
Subject: Re: [mm/sl[au]b] 3c4cafa313: canonical_address#:#[##]
Date: Fri, 09 Sep 2022 23:32:45 +0900 [thread overview]
Message-ID: <YxtOjYB9DvR4Fkdp@hyeyoo> (raw)
In-Reply-To: <3d178109-5981-f4ee-8fe5-4f1d0c557ed2@suse.cz>
[-- Attachment #1: Type: text/plain, Size: 4185 bytes --]
On Fri, Sep 09, 2022 at 03:44:19PM +0200, Vlastimil Babka wrote:
> On 9/9/22 13:05, Hyeonggon Yoo wrote:
> >> ----8<----
> >> From d6f9fbb33b908eb8162cc1f6ce7f7c970d0f285f Mon Sep 17 00:00:00 2001
> >> From: Vlastimil Babka <vbabka@suse.cz>
> >> Date: Fri, 9 Sep 2022 12:03:10 +0200
> >> Subject: [PATCH 2/3] mm/migrate: make isolate_movable_page() skip slab pages
> >>
> >> In the next commit we want to rearrange struct slab fields to allow a
> >> larger rcu_head. Afterwards, the page->mapping field will overlap
> >> with SLUB's "struct list_head slab_list", where the value of prev
> >> pointer can become LIST_POISON2, which is 0x122 + POISON_POINTER_DELTA.
> >> Unfortunately the bit 1 being set can confuse PageMovable() to be a
> >> false positive and cause a GPF as reported by lkp [1].
> >>
> >> To fix this, make isolate_movable_page() skip pages with the PageSlab
> >> flag set. This is a bit tricky as we need to add memory barriers to SLAB
> >> and SLUB's page allocation and freeing, and their counterparts to
> >> isolate_movable_page().
> >
> > Hello, I just took a quick grasp,
> > Is this approach okay with folio_test_anon()?
>
> Not if used on a completely random page as compaction scanners can, but
> relies on those being first tested for PageLRU or coming from a page table
> lookup etc.
> Not ideal huh. Well I could improve also by switching 'next' and 'slabs'
> field and relying on the fact that the value of LIST_POISON2 doesn't include
> 0x1, just 0x2.
What about swapping counters and freelist?
freelist should be always aligned.
diff --git a/mm/slab.h b/mm/slab.h
index 2c248864ea91..7d4762a39065 100644
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -27,17 +27,7 @@ struct slab {
struct kmem_cache *slab_cache;
union {
struct {
- union {
- struct list_head slab_list;
-#ifdef CONFIG_SLUB_CPU_PARTIAL
- struct {
- struct slab *next;
- int slabs; /* Nr of slabs left */
- };
-#endif
- };
/* Double-word boundary */
- void *freelist; /* first free object */
union {
unsigned long counters;
struct {
@@ -46,6 +36,16 @@ struct slab {
unsigned frozen:1;
};
};
+ void *freelist; /* first free object */
+ union {
+ struct list_head slab_list;
+#ifdef CONFIG_SLUB_CPU_PARTIAL
+ struct {
+ struct slab *next;
+ int slabs; /* Nr of slabs left */
+ };
+#endif
+ };
};
struct rcu_head rcu_head;
};
@@ -81,10 +81,14 @@ SLAB_MATCH(_refcount, __page_refcount);
#ifdef CONFIG_MEMCG
SLAB_MATCH(memcg_data, memcg_data);
#endif
+#ifdef CONFIG_SLUB
+SLAB_MATCH(mapping, freelist);
+#endif
+
#undef SLAB_MATCH
static_assert(sizeof(struct slab) <= sizeof(struct page));
#if defined(CONFIG_HAVE_CMPXCHG_DOUBLE) && defined(CONFIG_SLUB)
-static_assert(IS_ALIGNED(offsetof(struct slab, freelist), 16));
+static_assert(IS_ALIGNED(offsetof(struct slab, counters), 16));
#endif
/**
diff --git a/mm/slub.c b/mm/slub.c
index 2f9cb6e67de3..0c9595c63e33 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -487,9 +487,9 @@ static inline bool __cmpxchg_double_slab(struct kmem_cache *s, struct slab *slab
#if defined(CONFIG_HAVE_CMPXCHG_DOUBLE) && \
defined(CONFIG_HAVE_ALIGNED_STRUCT_PAGE)
if (s->flags & __CMPXCHG_DOUBLE) {
- if (cmpxchg_double(&slab->freelist, &slab->counters,
- freelist_old, counters_old,
- freelist_new, counters_new))
+ if (cmpxchg_double(&slab->counters, &slab->freelist,
+ counters_old, freelist_old,
+ counters_new, freelist_new))
return true;
} else
#endif
@@ -526,9 +526,9 @@ static inline bool cmpxchg_double_slab(struct kmem_cache *s, struct slab *slab,
#if defined(CONFIG_HAVE_CMPXCHG_DOUBLE) && \
defined(CONFIG_HAVE_ALIGNED_STRUCT_PAGE)
if (s->flags & __CMPXCHG_DOUBLE) {
- if (cmpxchg_double(&slab->freelist, &slab->counters,
- freelist_old, counters_old,
- freelist_new, counters_new))
+ if (cmpxchg_double(&slab->counters, &slab->freelist,
+ counters_old, freelist_old,
+ counters_new, freelist_new))
return true;
} else
#endif
--
Thanks,
Hyeonggon
WARNING: multiple messages have this Message-ID (diff)
From: Hyeonggon Yoo <42.hyeyoo@gmail.com>
To: Vlastimil Babka <vbabka@suse.cz>
Cc: kernel test robot <yujie.liu@intel.com>,
lkp@lists.01.org, lkp@intel.com,
Joel Fernandes <joel@joelfernandes.org>,
linux-mm@kvack.org, rcu@vger.kernel.org, paulmck@kernel.org,
Alexey Dobriyan <adobriyan@gmail.com>,
Matthew Wilcox <willy@infradead.org>
Subject: Re: [mm/sl[au]b] 3c4cafa313: canonical_address#:#[##]
Date: Fri, 9 Sep 2022 23:32:45 +0900 [thread overview]
Message-ID: <YxtOjYB9DvR4Fkdp@hyeyoo> (raw)
In-Reply-To: <3d178109-5981-f4ee-8fe5-4f1d0c557ed2@suse.cz>
On Fri, Sep 09, 2022 at 03:44:19PM +0200, Vlastimil Babka wrote:
> On 9/9/22 13:05, Hyeonggon Yoo wrote:
> >> ----8<----
> >> From d6f9fbb33b908eb8162cc1f6ce7f7c970d0f285f Mon Sep 17 00:00:00 2001
> >> From: Vlastimil Babka <vbabka@suse.cz>
> >> Date: Fri, 9 Sep 2022 12:03:10 +0200
> >> Subject: [PATCH 2/3] mm/migrate: make isolate_movable_page() skip slab pages
> >>
> >> In the next commit we want to rearrange struct slab fields to allow a
> >> larger rcu_head. Afterwards, the page->mapping field will overlap
> >> with SLUB's "struct list_head slab_list", where the value of prev
> >> pointer can become LIST_POISON2, which is 0x122 + POISON_POINTER_DELTA.
> >> Unfortunately the bit 1 being set can confuse PageMovable() to be a
> >> false positive and cause a GPF as reported by lkp [1].
> >>
> >> To fix this, make isolate_movable_page() skip pages with the PageSlab
> >> flag set. This is a bit tricky as we need to add memory barriers to SLAB
> >> and SLUB's page allocation and freeing, and their counterparts to
> >> isolate_movable_page().
> >
> > Hello, I just took a quick grasp,
> > Is this approach okay with folio_test_anon()?
>
> Not if used on a completely random page as compaction scanners can, but
> relies on those being first tested for PageLRU or coming from a page table
> lookup etc.
> Not ideal huh. Well I could improve also by switching 'next' and 'slabs'
> field and relying on the fact that the value of LIST_POISON2 doesn't include
> 0x1, just 0x2.
What about swapping counters and freelist?
freelist should be always aligned.
diff --git a/mm/slab.h b/mm/slab.h
index 2c248864ea91..7d4762a39065 100644
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -27,17 +27,7 @@ struct slab {
struct kmem_cache *slab_cache;
union {
struct {
- union {
- struct list_head slab_list;
-#ifdef CONFIG_SLUB_CPU_PARTIAL
- struct {
- struct slab *next;
- int slabs; /* Nr of slabs left */
- };
-#endif
- };
/* Double-word boundary */
- void *freelist; /* first free object */
union {
unsigned long counters;
struct {
@@ -46,6 +36,16 @@ struct slab {
unsigned frozen:1;
};
};
+ void *freelist; /* first free object */
+ union {
+ struct list_head slab_list;
+#ifdef CONFIG_SLUB_CPU_PARTIAL
+ struct {
+ struct slab *next;
+ int slabs; /* Nr of slabs left */
+ };
+#endif
+ };
};
struct rcu_head rcu_head;
};
@@ -81,10 +81,14 @@ SLAB_MATCH(_refcount, __page_refcount);
#ifdef CONFIG_MEMCG
SLAB_MATCH(memcg_data, memcg_data);
#endif
+#ifdef CONFIG_SLUB
+SLAB_MATCH(mapping, freelist);
+#endif
+
#undef SLAB_MATCH
static_assert(sizeof(struct slab) <= sizeof(struct page));
#if defined(CONFIG_HAVE_CMPXCHG_DOUBLE) && defined(CONFIG_SLUB)
-static_assert(IS_ALIGNED(offsetof(struct slab, freelist), 16));
+static_assert(IS_ALIGNED(offsetof(struct slab, counters), 16));
#endif
/**
diff --git a/mm/slub.c b/mm/slub.c
index 2f9cb6e67de3..0c9595c63e33 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -487,9 +487,9 @@ static inline bool __cmpxchg_double_slab(struct kmem_cache *s, struct slab *slab
#if defined(CONFIG_HAVE_CMPXCHG_DOUBLE) && \
defined(CONFIG_HAVE_ALIGNED_STRUCT_PAGE)
if (s->flags & __CMPXCHG_DOUBLE) {
- if (cmpxchg_double(&slab->freelist, &slab->counters,
- freelist_old, counters_old,
- freelist_new, counters_new))
+ if (cmpxchg_double(&slab->counters, &slab->freelist,
+ counters_old, freelist_old,
+ counters_new, freelist_new))
return true;
} else
#endif
@@ -526,9 +526,9 @@ static inline bool cmpxchg_double_slab(struct kmem_cache *s, struct slab *slab,
#if defined(CONFIG_HAVE_CMPXCHG_DOUBLE) && \
defined(CONFIG_HAVE_ALIGNED_STRUCT_PAGE)
if (s->flags & __CMPXCHG_DOUBLE) {
- if (cmpxchg_double(&slab->freelist, &slab->counters,
- freelist_old, counters_old,
- freelist_new, counters_new))
+ if (cmpxchg_double(&slab->counters, &slab->freelist,
+ counters_old, freelist_old,
+ counters_new, freelist_new))
return true;
} else
#endif
--
Thanks,
Hyeonggon
next prev parent reply other threads:[~2022-09-09 14:32 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20220906074548.GA72649@inn2.lkp.intel.com>
2022-09-06 7:51 ` [mm/sl[au]b] 3c4cafa313: canonical_address#:#[##] kernel test robot
2022-09-06 7:51 ` kernel test robot
2022-09-06 14:56 ` Hyeonggon Yoo
2022-09-06 14:56 ` Hyeonggon Yoo
2022-09-06 15:11 ` Vlastimil Babka
2022-09-06 15:11 ` Vlastimil Babka
2022-09-09 10:21 ` Vlastimil Babka
2022-09-09 10:21 ` Vlastimil Babka
2022-09-09 11:05 ` Hyeonggon Yoo
2022-09-09 11:05 ` Hyeonggon Yoo
2022-09-09 13:44 ` Vlastimil Babka
2022-09-09 13:44 ` Vlastimil Babka
2022-09-09 14:32 ` Hyeonggon Yoo [this message]
2022-09-09 14:32 ` Hyeonggon Yoo
2022-09-09 21:16 ` Vlastimil Babka
2022-09-09 21:16 ` Vlastimil Babka
2022-09-10 3:34 ` Hyeonggon Yoo
2022-09-10 3:34 ` Hyeonggon Yoo
2022-09-14 6:33 ` Hyeonggon Yoo
2022-09-14 6:33 ` Hyeonggon Yoo
2022-09-14 7:42 ` Matthew Wilcox
2022-09-14 7:42 ` Matthew Wilcox
2022-09-16 17:06 ` Vlastimil Babka
2022-09-16 17:06 ` Vlastimil Babka
2022-09-06 15:09 ` Hyeonggon Yoo
2022-09-06 15:09 ` Hyeonggon Yoo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=YxtOjYB9DvR4Fkdp@hyeyoo \
--to=42.hyeyoo@gmail.com \
--cc=lkp@lists.01.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.