linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
From: Konstantin Khlebnikov <koct9i@gmail.com>
To: linux-mm@kvack.org
Subject: [PATCH RFC v0 1/6] pagevec: segmented page vectors
Date: Mon, 15 Jun 2015 10:51:01 +0300	[thread overview]
Message-ID: <20150615075101.18112.67630.stgit@zurg> (raw)
In-Reply-To: <20150615073926.18112.59207.stgit@zurg>

This patch adds helpers for linking several page vectors into
segmented chain and macro for iterating over this chain.

For linking it uses space formerly used for field 'cold' which
is now stored as a lower bit in pointer to the next segment.

Signed-off-by: Konstantin Khlebnikov <koct9i@gmail.com>
---
 include/linux/pagevec.h |   48 ++++++++++++++++++++++++++++++++++++++++++++---
 mm/swap.c               |   44 +++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 87 insertions(+), 5 deletions(-)

diff --git a/include/linux/pagevec.h b/include/linux/pagevec.h
index b45d391..de3ea58 100644
--- a/include/linux/pagevec.h
+++ b/include/linux/pagevec.h
@@ -16,7 +16,7 @@ struct address_space;
 
 struct pagevec {
 	unsigned long nr;
-	unsigned long cold;
+	unsigned long _next;
 	struct page *pages[PAGEVEC_SIZE];
 };
 
@@ -32,11 +32,23 @@ unsigned pagevec_lookup(struct pagevec *pvec, struct address_space *mapping,
 unsigned pagevec_lookup_tag(struct pagevec *pvec,
 		struct address_space *mapping, pgoff_t *index, int tag,
 		unsigned nr_pages);
+struct pagevec *pagevec_extend(struct pagevec *pvec, gfp_t gfpmask);
+void pagevec_shrink(struct pagevec *pvec);
 
-static inline void pagevec_init(struct pagevec *pvec, int cold)
+static inline bool pagevec_cold(struct pagevec *pvec)
+{
+	return pvec->_next & 1;
+}
+
+static inline struct pagevec *pagevec_next(struct pagevec *pvec)
+{
+	return (struct pagevec *)(pvec->_next & ~1ul);
+}
+
+static inline void pagevec_init(struct pagevec *pvec, bool cold)
 {
 	pvec->nr = 0;
-	pvec->cold = cold;
+	pvec->_next = cold;
 }
 
 static inline void pagevec_reinit(struct pagevec *pvec)
@@ -69,4 +81,34 @@ static inline void pagevec_release(struct pagevec *pvec)
 		__pagevec_release(pvec);
 }
 
+/**
+ * pagevec_for_each_page - iterate over all pages in single page vector *
+ * @pv		pointer to page vector
+ * @i		int variable used as index
+ * @page	pointer to struct page
+ */
+#define pagevec_for_each_page(pv, i, page) \
+	for (i = 0; (i < (pv)->nr) && (page = (pv)->pages[i], true); i++)
+
+/**
+ * pagevec_for_each_vec - iterate over all segments in page vector
+ * @pv		pointer to head page vector
+ * @v		pointer for current page vector segment
+ */
+#define pagevec_for_each_vec(pv, v) \
+	for (v = (pv); v; v = pagevec_next(v))
+
+/**
+ * pagevec_for_each_vec_and_page - iterate over all pages in segmented vector
+ * @pv		pointer to head page vector
+ * @v		pointer for current page vector segment
+ * @i		int variable used index in current segment
+ * @page	pointer to struct page
+ *
+ * Warning: this is double loop, "break" does not work.
+ */
+#define pagevec_for_each_vec_and_page(pv, v, i, page) \
+	pagevec_for_each_vec(pv, v) \
+		pagevec_for_each_page(v, i, page)
+
 #endif /* _LINUX_PAGEVEC_H */
diff --git a/mm/swap.c b/mm/swap.c
index a7251a8..3ec0eb5 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -32,6 +32,7 @@
 #include <linux/gfp.h>
 #include <linux/uio.h>
 #include <linux/hugetlb.h>
+#include <linux/slab.h>
 
 #include "internal.h"
 
@@ -440,7 +441,7 @@ static void pagevec_lru_move_fn(struct pagevec *pvec,
 	}
 	if (zone)
 		spin_unlock_irqrestore(&zone->lru_lock, flags);
-	release_pages(pvec->pages, pvec->nr, pvec->cold);
+	release_pages(pvec->pages, pagevec_count(pvec), pagevec_cold(pvec));
 	pagevec_reinit(pvec);
 }
 
@@ -982,7 +983,7 @@ EXPORT_SYMBOL(release_pages);
 void __pagevec_release(struct pagevec *pvec)
 {
 	lru_add_drain();
-	release_pages(pvec->pages, pagevec_count(pvec), pvec->cold);
+	release_pages(pvec->pages, pagevec_count(pvec), pagevec_cold(pvec));
 	pagevec_reinit(pvec);
 }
 EXPORT_SYMBOL(__pagevec_release);
@@ -1137,6 +1138,45 @@ unsigned pagevec_lookup_tag(struct pagevec *pvec, struct address_space *mapping,
 }
 EXPORT_SYMBOL(pagevec_lookup_tag);
 
+/**
+ * pagevec_extend - allocate, initialize and link next page vector
+ * @pvec:	page vector for extending
+ * @gfpmask:
+ *
+ * Returns pointer to new page vector or NULL if allocation failed.
+ */
+struct pagevec *pagevec_extend(struct pagevec *pvec, gfp_t gfpmask)
+{
+	struct pagevec *next;
+
+	next = kmalloc(sizeof(struct pagevec), gfpmask);
+	if (next) {
+		bool cold = pagevec_cold(pvec);
+		pagevec_init(next, cold);
+		pvec->_next = (unsigned long)next + cold;
+	}
+	return next;
+}
+
+/**
+ * pagevec_shrink - free all following page vectors segments
+ * @pvec:	head page vector
+ *
+ * Head vector and pages are not freed.
+ */
+void pagevec_shrink(struct pagevec *head)
+{
+	struct pagevec *pvec, *next;
+
+	pvec = pagevec_next(head);
+	head->_next &= 1ul;
+	while (pvec) {
+		next = pagevec_next(pvec);
+		kfree(pvec);
+		pvec = next;
+	}
+}
+
 /*
  * Perform any setup for the swap system
  */

--
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>

  reply	other threads:[~2015-06-15  7:51 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-06-15  7:50 [PATCH RFC v0 0/6] mm: proof-of-concept memory compaction without isolation Konstantin Khlebnikov
2015-06-15  7:51 ` Konstantin Khlebnikov [this message]
2015-06-15  7:51 ` [PATCH RFC v0 2/6] mm/migrate: move putback of old page out of unmap_and_move Konstantin Khlebnikov
2015-06-15  7:51 ` [PATCH RFC v0 3/6] mm/cma: repalce reclaim_clean_pages_from_list with try_to_reclaim_page Konstantin Khlebnikov
2015-06-15  7:51 ` [PATCH RFC v0 4/6] mm/migrate: page migration without page isolation Konstantin Khlebnikov
2015-06-15  7:51 ` [PATCH RFC v0 5/6] mm/compaction: use migration without isolation Konstantin Khlebnikov
2015-06-15  7:51 ` [PATCH RFC v0 6/6] mm/migrate: preserve lru order if possible Konstantin Khlebnikov
2015-06-15  9:52 ` [PATCH RFC v0 0/6] mm: proof-of-concept memory compaction without isolation Vlastimil Babka

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=20150615075101.18112.67630.stgit@zurg \
    --to=koct9i@gmail.com \
    --cc=linux-mm@kvack.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 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).