randprotect: KSM: add batch random generator helper
can_write_protect() returns a random boolean generated from a 50%
Bernoulli distribution (p = 1/2). This is an helper required later.
Signed-off-by: Andrea Arcangeli <aarcange@redhat.com>
diff --git a/mm/ksm.c b/mm/ksm.c
index d809008..f82cea5 100644
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -38,6 +38,7 @@
#include <linux/freezer.h>
#include <linux/oom.h>
#include <linux/numa.h>
+#include <linux/random.h>
#include <asm/tlbflush.h>
#include "internal.h"
@@ -124,12 +125,19 @@ struct mm_slot {
struct mm_struct *mm;
};
+#define NR_RANDOM_LONGS 8
+struct random_batch {
+ unsigned long bits[NR_RANDOM_LONGS];
+ unsigned int bit;
+};
+
/**
* struct ksm_scan - cursor for scanning
* @mm_slot: the current mm_slot we are scanning
* @address: the next address inside that to be scanned
* @rmap_list: link to the next rmap to be scanned in the rmap_list
* @seqnr: count of completed full scans (needed when removing unstable node)
+ * @random_bytes: random payload batching
*
* There is only the one ksm_scan instance of this cursor structure.
*/
@@ -138,6 +146,7 @@ struct ksm_scan {
unsigned long address;
struct rmap_item **rmap_list;
unsigned long seqnr;
+ struct random_batch random_batch;
};
/**
@@ -301,6 +310,23 @@ static DEFINE_SPINLOCK(ksm_mmlist_lock);
sizeof(struct __struct), __alignof__(struct __struct),\
(__flags), NULL)
+/*
+ * Decide if to write protect pages whose payload didn't change over
+ * the last KSM scans (according to checksum) based on a Bernoulli
+ * distribution with p = 1/2.
+ */
+static bool can_write_protect(void)
+{
+ struct random_batch *random = &ksm_scan.random_batch;
+ if (!random->bit) {
+ get_random_bytes(&random->bits,
+ sizeof(random->bits));
+ random->bit = sizeof(random->bits) * 8;
+ }
+ random->bit--;
+ return test_bit(random->bit, random->bits);
+}
+
static int __init ksm_slab_init(void)
{
rmap_item_cache = KSM_KMEM_CACHE(rmap_item, 0);