From: Minchan Kim <minchan@kernel.org>
Cc: Kamezawa Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>,
KOSAKI Motohiro <kosaki.motohiro@gmail.com>,
Aaditya Kumar <aaditya.kumar.30@gmail.com>,
Mel Gorman <mel@csn.ul.ie>,
"linux-mm@kvack.org" <linux-mm@kvack.org>,
LKML <linux-kernel@vger.kernel.org>
Subject: Re: Accounting problem of MIGRATE_ISOLATED freed page
Date: Fri, 22 Jun 2012 15:45:54 +0900 [thread overview]
Message-ID: <4FE414A2.3000700@kernel.org> (raw)
In-Reply-To: <4FE3C4E4.2050107@kernel.org>
On 06/22/2012 10:05 AM, Minchan Kim wrote:
> Second approach which is suggested by KOSAKI is what you mentioned.
> But the concern about second approach is how to make sure matched count increase/decrease of nr_isolated_areas.
> I mean how to make sure nr_isolated_areas would be zero when isolation is done.
> Of course, we can investigate all of current caller and make sure they don't make mistake
> now. But it's very error-prone if we consider future's user.
> So we might need test_set_pageblock_migratetype(page, MIGRATE_ISOLATE);
It's an implementation about above approach.
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index bf3404e..3e9a9e1 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -474,6 +474,11 @@ struct zone {
* rarely used fields:
*/
const char *name;
+ /*
+ * the number of MIGRATE_ISOLATE pageblock
+ * We need this for accurate free page counting.
+ */
+ atomic_t nr_migrate_isolate;
} ____cacheline_internodealigned_in_smp;
typedef enum {
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 2c29b1c..6cb1f9f 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -219,6 +219,11 @@ EXPORT_SYMBOL(nr_online_nodes);
int page_group_by_mobility_disabled __read_mostly;
+/*
+ * NOTE:
+ * Don't use set_pageblock_migratetype(page, MIGRATE_ISOLATE) direclty.
+ * Instead, use {un}set_pageblock_isolate.
+ */
void set_pageblock_migratetype(struct page *page, int migratetype)
{
if (unlikely(page_group_by_mobility_disabled))
@@ -1622,6 +1627,28 @@ bool zone_watermark_ok(struct zone *z, int order, unsigned long mark,
zone_page_state(z, NR_FREE_PAGES));
}
+unsigned long migrate_isolate_pages(struct zone *zone)
+{
+ unsigned long nr_pages = 0;
+
+ if (unlikely(atomic_read(&zone->nr_migrate_isolate))) {
+ unsigned long flags;
+ int order;
+ spin_lock_irqsave(&zone->lock, flags);
+ for (order = 0; order < MAX_ORDER; order++) {
+ struct free_area *area = &zone->free_area[order];
+ long count = 0;
+ struct list_head *curr;
+
+ list_for_each(curr, &area->free_list[MIGRATE_ISOLATE])
+ count++;
+ nr_pages += (count << order);
+ }
+ spin_unlock_irqrestore(&zone->lock, flags);
+ }
+ return nr_pages;
+}
+
bool zone_watermark_ok_safe(struct zone *z, int order, unsigned long mark,
int classzone_idx, int alloc_flags)
{
@@ -1630,6 +1657,14 @@ bool zone_watermark_ok_safe(struct zone *z, int order, unsigned long mark,
if (z->percpu_drift_mark && free_pages < z->percpu_drift_mark)
free_pages = zone_page_state_snapshot(z, NR_FREE_PAGES);
+ /*
+ * If the zone has MIGRATE_ISOLATE type free page,
+ * we should consider it, too. Otherwise, kswapd can sleep forever.
+ */
+ free_pages -= migrate_isolate_pages(z);
+ if (free_pages < 0)
+ free_pages = 0;
+
return __zone_watermark_ok(z, order, mark, classzone_idx, alloc_flags,
free_pages);
}
@@ -4408,6 +4443,7 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat,
lruvec_init(&zone->lruvec, zone);
zap_zone_vm_stats(zone);
zone->flags = 0;
+ atomic_set(&zone->nr_migrate_isolate, 0);
if (!size)
continue;
@@ -5555,6 +5591,45 @@ bool is_pageblock_removable_nolock(struct page *page)
return __count_immobile_pages(zone, page, 0);
}
+static void set_pageblock_isolate(struct zone *zone, struct page *page)
+{
+ int old_migratetype;
+ assert_spin_locked(&zone->lock);
+
+ if (unlikely(page_group_by_mobility_disabled)) {
+ set_pageblock_flags_group(page, MIGRATE_UNMOVABLE,
+ PB_migrate, PB_migrate_end);
+ return;
+ }
+
+ old_migratetype = get_pageblock_migratetype(page);
+ set_pageblock_flags_group(page, MIGRATE_ISOLATE,
+ PB_migrate, PB_migrate_end);
+
+ if (old_migratetype != MIGRATE_ISOLATE)
+ atomic_inc(&zone->nr_migrate_isolate);
+}
+
+static void unset_pageblock_isolate(struct zone *zone, struct page *page,
+ unsigned long migratetype)
+{
+ assert_spin_locked(&zone->lock);
+
+ if (unlikely(page_group_by_mobility_disabled)) {
+ set_pageblock_flags_group(page, migratetype,
+ PB_migrate, PB_migrate_end);
+ return;
+ }
+
+ BUG_ON(get_pageblock_migratetype(page) != MIGRATE_ISOLATE);
+ BUG_ON(migratetype == MIGRATE_ISOLATE);
+
+ set_pageblock_flags_group(page, migratetype,
+ PB_migrate, PB_migrate_end);
+ atomic_dec(&zone->nr_migrate_isolate);
+ BUG_ON(atomic_read(&zone->nr_migrate_isolate) < 0);
+}
+
int set_migratetype_isolate(struct page *page)
{
struct zone *zone;
@@ -5601,7 +5676,7 @@ int set_migratetype_isolate(struct page *page)
out:
if (!ret) {
- set_pageblock_migratetype(page, MIGRATE_ISOLATE);
+ set_pageblock_isolate(zone, page);
move_freepages_block(zone, page, MIGRATE_ISOLATE);
}
@@ -5619,8 +5694,8 @@ void unset_migratetype_isolate(struct page *page, unsigned migratetype)
spin_lock_irqsave(&zone->lock, flags);
if (get_pageblock_migratetype(page) != MIGRATE_ISOLATE)
goto out;
- set_pageblock_migratetype(page, migratetype);
move_freepages_block(zone, page, migratetype);
+ unset_pageblock_isolate(zone, page, migratetype);
out:
spin_unlock_irqrestore(&zone->lock, flags);
}
--
1.7.9.5
--
Kind regards,
Minchan Kim
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
next prev parent reply other threads:[~2012-06-22 6:45 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-06-20 6:12 Accounting problem of MIGRATE_ISOLATED freed page Minchan Kim
2012-06-20 6:32 ` KOSAKI Motohiro
2012-06-20 7:53 ` Minchan Kim
2012-06-20 12:44 ` Hillf Danton
2012-06-20 23:58 ` Minchan Kim
2012-06-20 20:19 ` KOSAKI Motohiro
2012-06-21 0:01 ` Minchan Kim
2012-06-21 1:39 ` KOSAKI Motohiro
2012-06-21 1:55 ` Minchan Kim
2012-06-21 2:45 ` KOSAKI Motohiro
2012-06-21 4:55 ` Minchan Kim
2012-06-21 10:52 ` Kamezawa Hiroyuki
2012-06-21 17:22 ` KOSAKI Motohiro
2012-06-22 1:05 ` Minchan Kim
2012-06-22 6:45 ` Minchan Kim [this message]
2012-06-23 2:56 ` KOSAKI Motohiro
2012-06-25 1:10 ` Minchan Kim
2012-06-23 2:59 ` KOSAKI Motohiro
2012-06-25 1:19 ` Minchan Kim
2012-06-23 4:38 ` Kamezawa Hiroyuki
2012-06-25 1:01 ` Minchan Kim
2012-06-25 4:18 ` Minchan Kim
2012-06-22 7:22 ` KOSAKI Motohiro
2012-06-22 7:56 ` Aaditya Kumar
2012-06-22 8:13 ` KOSAKI Motohiro
2012-06-21 11:02 ` Aaditya Kumar
2012-06-22 1:20 ` Minchan Kim
2012-06-22 2:08 ` Aaditya Kumar
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=4FE414A2.3000700@kernel.org \
--to=minchan@kernel.org \
--cc=aaditya.kumar.30@gmail.com \
--cc=kamezawa.hiroyu@jp.fujitsu.com \
--cc=kosaki.motohiro@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=mel@csn.ul.ie \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).