diff options
Diffstat (limited to 'mm/huge_memory.c')
-rw-r--r-- | mm/huge_memory.c | 54 |
1 files changed, 9 insertions, 45 deletions
diff --git a/mm/huge_memory.c b/mm/huge_memory.c index b5783d81eda9..9db521fa8e8a 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/mman.h> | 20 | #include <linux/mman.h> |
21 | #include <linux/pagemap.h> | 21 | #include <linux/pagemap.h> |
22 | #include <linux/migrate.h> | 22 | #include <linux/migrate.h> |
23 | #include <linux/hashtable.h> | ||
23 | 24 | ||
24 | #include <asm/tlb.h> | 25 | #include <asm/tlb.h> |
25 | #include <asm/pgalloc.h> | 26 | #include <asm/pgalloc.h> |
@@ -62,12 +63,11 @@ static DECLARE_WAIT_QUEUE_HEAD(khugepaged_wait); | |||
62 | static unsigned int khugepaged_max_ptes_none __read_mostly = HPAGE_PMD_NR-1; | 63 | static unsigned int khugepaged_max_ptes_none __read_mostly = HPAGE_PMD_NR-1; |
63 | 64 | ||
64 | static int khugepaged(void *none); | 65 | static int khugepaged(void *none); |
65 | static int mm_slots_hash_init(void); | ||
66 | static int khugepaged_slab_init(void); | 66 | static int khugepaged_slab_init(void); |
67 | static void khugepaged_slab_free(void); | ||
68 | 67 | ||
69 | #define MM_SLOTS_HASH_HEADS 1024 | 68 | #define MM_SLOTS_HASH_BITS 10 |
70 | static struct hlist_head *mm_slots_hash __read_mostly; | 69 | static __read_mostly DEFINE_HASHTABLE(mm_slots_hash, MM_SLOTS_HASH_BITS); |
70 | |||
71 | static struct kmem_cache *mm_slot_cache __read_mostly; | 71 | static struct kmem_cache *mm_slot_cache __read_mostly; |
72 | 72 | ||
73 | /** | 73 | /** |
@@ -634,12 +634,6 @@ static int __init hugepage_init(void) | |||
634 | if (err) | 634 | if (err) |
635 | goto out; | 635 | goto out; |
636 | 636 | ||
637 | err = mm_slots_hash_init(); | ||
638 | if (err) { | ||
639 | khugepaged_slab_free(); | ||
640 | goto out; | ||
641 | } | ||
642 | |||
643 | register_shrinker(&huge_zero_page_shrinker); | 637 | register_shrinker(&huge_zero_page_shrinker); |
644 | 638 | ||
645 | /* | 639 | /* |
@@ -1908,12 +1902,6 @@ static int __init khugepaged_slab_init(void) | |||
1908 | return 0; | 1902 | return 0; |
1909 | } | 1903 | } |
1910 | 1904 | ||
1911 | static void __init khugepaged_slab_free(void) | ||
1912 | { | ||
1913 | kmem_cache_destroy(mm_slot_cache); | ||
1914 | mm_slot_cache = NULL; | ||
1915 | } | ||
1916 | |||
1917 | static inline struct mm_slot *alloc_mm_slot(void) | 1905 | static inline struct mm_slot *alloc_mm_slot(void) |
1918 | { | 1906 | { |
1919 | if (!mm_slot_cache) /* initialization failed */ | 1907 | if (!mm_slot_cache) /* initialization failed */ |
@@ -1926,47 +1914,23 @@ static inline void free_mm_slot(struct mm_slot *mm_slot) | |||
1926 | kmem_cache_free(mm_slot_cache, mm_slot); | 1914 | kmem_cache_free(mm_slot_cache, mm_slot); |
1927 | } | 1915 | } |
1928 | 1916 | ||
1929 | static int __init mm_slots_hash_init(void) | ||
1930 | { | ||
1931 | mm_slots_hash = kzalloc(MM_SLOTS_HASH_HEADS * sizeof(struct hlist_head), | ||
1932 | GFP_KERNEL); | ||
1933 | if (!mm_slots_hash) | ||
1934 | return -ENOMEM; | ||
1935 | return 0; | ||
1936 | } | ||
1937 | |||
1938 | #if 0 | ||
1939 | static void __init mm_slots_hash_free(void) | ||
1940 | { | ||
1941 | kfree(mm_slots_hash); | ||
1942 | mm_slots_hash = NULL; | ||
1943 | } | ||
1944 | #endif | ||
1945 | |||
1946 | static struct mm_slot *get_mm_slot(struct mm_struct *mm) | 1917 | static struct mm_slot *get_mm_slot(struct mm_struct *mm) |
1947 | { | 1918 | { |
1948 | struct mm_slot *mm_slot; | 1919 | struct mm_slot *mm_slot; |
1949 | struct hlist_head *bucket; | ||
1950 | struct hlist_node *node; | 1920 | struct hlist_node *node; |
1951 | 1921 | ||
1952 | bucket = &mm_slots_hash[((unsigned long)mm / sizeof(struct mm_struct)) | 1922 | hash_for_each_possible(mm_slots_hash, mm_slot, node, hash, (unsigned long)mm) |
1953 | % MM_SLOTS_HASH_HEADS]; | ||
1954 | hlist_for_each_entry(mm_slot, node, bucket, hash) { | ||
1955 | if (mm == mm_slot->mm) | 1923 | if (mm == mm_slot->mm) |
1956 | return mm_slot; | 1924 | return mm_slot; |
1957 | } | 1925 | |
1958 | return NULL; | 1926 | return NULL; |
1959 | } | 1927 | } |
1960 | 1928 | ||
1961 | static void insert_to_mm_slots_hash(struct mm_struct *mm, | 1929 | static void insert_to_mm_slots_hash(struct mm_struct *mm, |
1962 | struct mm_slot *mm_slot) | 1930 | struct mm_slot *mm_slot) |
1963 | { | 1931 | { |
1964 | struct hlist_head *bucket; | ||
1965 | |||
1966 | bucket = &mm_slots_hash[((unsigned long)mm / sizeof(struct mm_struct)) | ||
1967 | % MM_SLOTS_HASH_HEADS]; | ||
1968 | mm_slot->mm = mm; | 1932 | mm_slot->mm = mm; |
1969 | hlist_add_head(&mm_slot->hash, bucket); | 1933 | hash_add(mm_slots_hash, &mm_slot->hash, (long)mm); |
1970 | } | 1934 | } |
1971 | 1935 | ||
1972 | static inline int khugepaged_test_exit(struct mm_struct *mm) | 1936 | static inline int khugepaged_test_exit(struct mm_struct *mm) |
@@ -2035,7 +1999,7 @@ void __khugepaged_exit(struct mm_struct *mm) | |||
2035 | spin_lock(&khugepaged_mm_lock); | 1999 | spin_lock(&khugepaged_mm_lock); |
2036 | mm_slot = get_mm_slot(mm); | 2000 | mm_slot = get_mm_slot(mm); |
2037 | if (mm_slot && khugepaged_scan.mm_slot != mm_slot) { | 2001 | if (mm_slot && khugepaged_scan.mm_slot != mm_slot) { |
2038 | hlist_del(&mm_slot->hash); | 2002 | hash_del(&mm_slot->hash); |
2039 | list_del(&mm_slot->mm_node); | 2003 | list_del(&mm_slot->mm_node); |
2040 | free = 1; | 2004 | free = 1; |
2041 | } | 2005 | } |
@@ -2484,7 +2448,7 @@ static void collect_mm_slot(struct mm_slot *mm_slot) | |||
2484 | 2448 | ||
2485 | if (khugepaged_test_exit(mm)) { | 2449 | if (khugepaged_test_exit(mm)) { |
2486 | /* free mm_slot */ | 2450 | /* free mm_slot */ |
2487 | hlist_del(&mm_slot->hash); | 2451 | hash_del(&mm_slot->hash); |
2488 | list_del(&mm_slot->mm_node); | 2452 | list_del(&mm_slot->mm_node); |
2489 | 2453 | ||
2490 | /* | 2454 | /* |