diff options
-rw-r--r-- | mm/ksm.c | 38 |
1 files changed, 9 insertions, 29 deletions
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/mmu_notifier.h> | 33 | #include <linux/mmu_notifier.h> |
34 | #include <linux/swap.h> | 34 | #include <linux/swap.h> |
35 | #include <linux/ksm.h> | 35 | #include <linux/ksm.h> |
36 | #include <linux/hash.h> | ||
36 | 37 | ||
37 | #include <asm/tlbflush.h> | 38 | #include <asm/tlbflush.h> |
38 | #include "internal.h" | 39 | #include "internal.h" |
@@ -153,8 +154,9 @@ struct rmap_item { | |||
153 | static struct rb_root root_stable_tree = RB_ROOT; | 154 | static struct rb_root root_stable_tree = RB_ROOT; |
154 | static struct rb_root root_unstable_tree = RB_ROOT; | 155 | static struct rb_root root_unstable_tree = RB_ROOT; |
155 | 156 | ||
156 | #define MM_SLOTS_HASH_HEADS 1024 | 157 | #define MM_SLOTS_HASH_SHIFT 10 |
157 | static struct hlist_head *mm_slots_hash; | 158 | #define MM_SLOTS_HASH_HEADS (1 << MM_SLOTS_HASH_SHIFT) |
159 | static struct hlist_head mm_slots_hash[MM_SLOTS_HASH_HEADS]; | ||
158 | 160 | ||
159 | static struct mm_slot ksm_mm_head = { | 161 | static struct mm_slot ksm_mm_head = { |
160 | .mm_list = LIST_HEAD_INIT(ksm_mm_head.mm_list), | 162 | .mm_list = LIST_HEAD_INIT(ksm_mm_head.mm_list), |
@@ -269,28 +271,13 @@ static inline void free_mm_slot(struct mm_slot *mm_slot) | |||
269 | kmem_cache_free(mm_slot_cache, mm_slot); | 271 | kmem_cache_free(mm_slot_cache, mm_slot); |
270 | } | 272 | } |
271 | 273 | ||
272 | static int __init mm_slots_hash_init(void) | ||
273 | { | ||
274 | mm_slots_hash = kzalloc(MM_SLOTS_HASH_HEADS * sizeof(struct hlist_head), | ||
275 | GFP_KERNEL); | ||
276 | if (!mm_slots_hash) | ||
277 | return -ENOMEM; | ||
278 | return 0; | ||
279 | } | ||
280 | |||
281 | static void __init mm_slots_hash_free(void) | ||
282 | { | ||
283 | kfree(mm_slots_hash); | ||
284 | } | ||
285 | |||
286 | static struct mm_slot *get_mm_slot(struct mm_struct *mm) | 274 | static struct mm_slot *get_mm_slot(struct mm_struct *mm) |
287 | { | 275 | { |
288 | struct mm_slot *mm_slot; | 276 | struct mm_slot *mm_slot; |
289 | struct hlist_head *bucket; | 277 | struct hlist_head *bucket; |
290 | struct hlist_node *node; | 278 | struct hlist_node *node; |
291 | 279 | ||
292 | bucket = &mm_slots_hash[((unsigned long)mm / sizeof(struct mm_struct)) | 280 | bucket = &mm_slots_hash[hash_ptr(mm, MM_SLOTS_HASH_SHIFT)]; |
293 | % MM_SLOTS_HASH_HEADS]; | ||
294 | hlist_for_each_entry(mm_slot, node, bucket, link) { | 281 | hlist_for_each_entry(mm_slot, node, bucket, link) { |
295 | if (mm == mm_slot->mm) | 282 | if (mm == mm_slot->mm) |
296 | return mm_slot; | 283 | return mm_slot; |
@@ -303,8 +290,7 @@ static void insert_to_mm_slots_hash(struct mm_struct *mm, | |||
303 | { | 290 | { |
304 | struct hlist_head *bucket; | 291 | struct hlist_head *bucket; |
305 | 292 | ||
306 | bucket = &mm_slots_hash[((unsigned long)mm / sizeof(struct mm_struct)) | 293 | bucket = &mm_slots_hash[hash_ptr(mm, MM_SLOTS_HASH_SHIFT)]; |
307 | % MM_SLOTS_HASH_HEADS]; | ||
308 | mm_slot->mm = mm; | 294 | mm_slot->mm = mm; |
309 | hlist_add_head(&mm_slot->link, bucket); | 295 | hlist_add_head(&mm_slot->link, bucket); |
310 | } | 296 | } |
@@ -1938,15 +1924,11 @@ static int __init ksm_init(void) | |||
1938 | if (err) | 1924 | if (err) |
1939 | goto out; | 1925 | goto out; |
1940 | 1926 | ||
1941 | err = mm_slots_hash_init(); | ||
1942 | if (err) | ||
1943 | goto out_free1; | ||
1944 | |||
1945 | ksm_thread = kthread_run(ksm_scan_thread, NULL, "ksmd"); | 1927 | ksm_thread = kthread_run(ksm_scan_thread, NULL, "ksmd"); |
1946 | if (IS_ERR(ksm_thread)) { | 1928 | if (IS_ERR(ksm_thread)) { |
1947 | printk(KERN_ERR "ksm: creating kthread failed\n"); | 1929 | printk(KERN_ERR "ksm: creating kthread failed\n"); |
1948 | err = PTR_ERR(ksm_thread); | 1930 | err = PTR_ERR(ksm_thread); |
1949 | goto out_free2; | 1931 | goto out_free; |
1950 | } | 1932 | } |
1951 | 1933 | ||
1952 | #ifdef CONFIG_SYSFS | 1934 | #ifdef CONFIG_SYSFS |
@@ -1954,7 +1936,7 @@ static int __init ksm_init(void) | |||
1954 | if (err) { | 1936 | if (err) { |
1955 | printk(KERN_ERR "ksm: register sysfs failed\n"); | 1937 | printk(KERN_ERR "ksm: register sysfs failed\n"); |
1956 | kthread_stop(ksm_thread); | 1938 | kthread_stop(ksm_thread); |
1957 | goto out_free2; | 1939 | goto out_free; |
1958 | } | 1940 | } |
1959 | #else | 1941 | #else |
1960 | ksm_run = KSM_RUN_MERGE; /* no way for user to start it */ | 1942 | ksm_run = KSM_RUN_MERGE; /* no way for user to start it */ |
@@ -1970,9 +1952,7 @@ static int __init ksm_init(void) | |||
1970 | #endif | 1952 | #endif |
1971 | return 0; | 1953 | return 0; |
1972 | 1954 | ||
1973 | out_free2: | 1955 | out_free: |
1974 | mm_slots_hash_free(); | ||
1975 | out_free1: | ||
1976 | ksm_slab_free(); | 1956 | ksm_slab_free(); |
1977 | out: | 1957 | out: |
1978 | return err; | 1958 | return err; |