aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHugh Dickins <hugh.dickins@tiscali.co.uk>2009-12-14 20:59:20 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-12-15 11:53:19 -0500
commit7b6ba2c7d3baf8cd9f888e05563dcc32e368baab (patch)
tree89e62613a37d803e4a83b96559acca29526f9638
parent6514d511dbe5a77b4bdc0a7e26fd679585112e1e (diff)
ksm: separate stable_node
Though we still do well to keep rmap_items in the unstable tree without a separate tree_item at the node, for several reasons it becomes awkward to keep rmap_items in the stable tree without a separate stable_node: lack of space in the nicely-sized rmap_item, the need for an anchor as rmap_items are removed, the need for a node even when temporarily no rmap_items are attached to it. So declare struct stable_node (rb_node to place it in the tree and hlist_head for the rmap_items hanging off it), and convert stable tree handling to use it: without yet taking advantage of it. Note how one stable_tree_insert() of a node now has _two_ stable_tree_append()s of the two rmap_items being merged. Signed-off-by: Hugh Dickins <hugh.dickins@tiscali.co.uk> Cc: Izik Eidus <ieidus@redhat.com> Cc: Andrea Arcangeli <aarcange@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--mm/ksm.c180
1 files changed, 101 insertions, 79 deletions
diff --git a/mm/ksm.c b/mm/ksm.c
index e8e9a2bca809..9b7af2eb4280 100644
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -106,34 +106,44 @@ struct ksm_scan {
106}; 106};
107 107
108/** 108/**
109 * struct stable_node - node of the stable rbtree
110 * @node: rb node of this ksm page in the stable tree
111 * @hlist: hlist head of rmap_items using this ksm page
112 */
113struct stable_node {
114 struct rb_node node;
115 struct hlist_head hlist;
116};
117
118/**
109 * struct rmap_item - reverse mapping item for virtual addresses 119 * struct rmap_item - reverse mapping item for virtual addresses
110 * @rmap_list: next rmap_item in mm_slot's singly-linked rmap_list 120 * @rmap_list: next rmap_item in mm_slot's singly-linked rmap_list
111 * @filler: unused space we're making available in this patch 121 * @filler: unused space we're making available in this patch
112 * @mm: the memory structure this rmap_item is pointing into 122 * @mm: the memory structure this rmap_item is pointing into
113 * @address: the virtual address this rmap_item tracks (+ flags in low bits) 123 * @address: the virtual address this rmap_item tracks (+ flags in low bits)
114 * @oldchecksum: previous checksum of the page at that virtual address 124 * @oldchecksum: previous checksum of the page at that virtual address
115 * @node: rb_node of this rmap_item in either unstable or stable tree 125 * @node: rb node of this rmap_item in the unstable tree
116 * @next: next rmap_item hanging off the same node of the stable tree 126 * @head: pointer to stable_node heading this list in the stable tree
117 * @prev: previous rmap_item hanging off the same node of the stable tree 127 * @hlist: link into hlist of rmap_items hanging off that stable_node
118 */ 128 */
119struct rmap_item { 129struct rmap_item {
120 struct rmap_item *rmap_list; 130 struct rmap_item *rmap_list;
121 unsigned long filler; 131 unsigned long filler;
122 struct mm_struct *mm; 132 struct mm_struct *mm;
123 unsigned long address; /* + low bits used for flags below */ 133 unsigned long address; /* + low bits used for flags below */
134 unsigned int oldchecksum; /* when unstable */
124 union { 135 union {
125 unsigned int oldchecksum; /* when unstable */ 136 struct rb_node node; /* when node of unstable tree */
126 struct rmap_item *next; /* when stable */ 137 struct { /* when listed from stable tree */
127 }; 138 struct stable_node *head;
128 union { 139 struct hlist_node hlist;
129 struct rb_node node; /* when tree node */ 140 };
130 struct rmap_item *prev; /* in stable list */
131 }; 141 };
132}; 142};
133 143
134#define SEQNR_MASK 0x0ff /* low bits of unstable tree seqnr */ 144#define SEQNR_MASK 0x0ff /* low bits of unstable tree seqnr */
135#define NODE_FLAG 0x100 /* is a node of unstable or stable tree */ 145#define UNSTABLE_FLAG 0x100 /* is a node of the unstable tree */
136#define STABLE_FLAG 0x200 /* is a node or list item of stable tree */ 146#define STABLE_FLAG 0x200 /* is listed from the stable tree */
137 147
138/* The stable and unstable tree heads */ 148/* The stable and unstable tree heads */
139static struct rb_root root_stable_tree = RB_ROOT; 149static struct rb_root root_stable_tree = RB_ROOT;
@@ -150,6 +160,7 @@ static struct ksm_scan ksm_scan = {
150}; 160};
151 161
152static struct kmem_cache *rmap_item_cache; 162static struct kmem_cache *rmap_item_cache;
163static struct kmem_cache *stable_node_cache;
153static struct kmem_cache *mm_slot_cache; 164static struct kmem_cache *mm_slot_cache;
154 165
155/* The number of nodes in the stable tree */ 166/* The number of nodes in the stable tree */
@@ -192,13 +203,19 @@ static int __init ksm_slab_init(void)
192 if (!rmap_item_cache) 203 if (!rmap_item_cache)
193 goto out; 204 goto out;
194 205
206 stable_node_cache = KSM_KMEM_CACHE(stable_node, 0);
207 if (!stable_node_cache)
208 goto out_free1;
209
195 mm_slot_cache = KSM_KMEM_CACHE(mm_slot, 0); 210 mm_slot_cache = KSM_KMEM_CACHE(mm_slot, 0);
196 if (!mm_slot_cache) 211 if (!mm_slot_cache)
197 goto out_free; 212 goto out_free2;
198 213
199 return 0; 214 return 0;
200 215
201out_free: 216out_free2:
217 kmem_cache_destroy(stable_node_cache);
218out_free1:
202 kmem_cache_destroy(rmap_item_cache); 219 kmem_cache_destroy(rmap_item_cache);
203out: 220out:
204 return -ENOMEM; 221 return -ENOMEM;
@@ -207,6 +224,7 @@ out:
207static void __init ksm_slab_free(void) 224static void __init ksm_slab_free(void)
208{ 225{
209 kmem_cache_destroy(mm_slot_cache); 226 kmem_cache_destroy(mm_slot_cache);
227 kmem_cache_destroy(stable_node_cache);
210 kmem_cache_destroy(rmap_item_cache); 228 kmem_cache_destroy(rmap_item_cache);
211 mm_slot_cache = NULL; 229 mm_slot_cache = NULL;
212} 230}
@@ -228,6 +246,16 @@ static inline void free_rmap_item(struct rmap_item *rmap_item)
228 kmem_cache_free(rmap_item_cache, rmap_item); 246 kmem_cache_free(rmap_item_cache, rmap_item);
229} 247}
230 248
249static inline struct stable_node *alloc_stable_node(void)
250{
251 return kmem_cache_alloc(stable_node_cache, GFP_KERNEL);
252}
253
254static inline void free_stable_node(struct stable_node *stable_node)
255{
256 kmem_cache_free(stable_node_cache, stable_node);
257}
258
231static inline struct mm_slot *alloc_mm_slot(void) 259static inline struct mm_slot *alloc_mm_slot(void)
232{ 260{
233 if (!mm_slot_cache) /* initialization failed */ 261 if (!mm_slot_cache) /* initialization failed */
@@ -429,36 +457,22 @@ static struct page *get_ksm_page(struct rmap_item *rmap_item)
429 */ 457 */
430static void remove_rmap_item_from_tree(struct rmap_item *rmap_item) 458static void remove_rmap_item_from_tree(struct rmap_item *rmap_item)
431{ 459{
432 if (in_stable_tree(rmap_item)) { 460 if (rmap_item->address & STABLE_FLAG) {
433 struct rmap_item *next_item = rmap_item->next; 461 struct stable_node *stable_node;
434
435 if (rmap_item->address & NODE_FLAG) {
436 if (next_item) {
437 rb_replace_node(&rmap_item->node,
438 &next_item->node,
439 &root_stable_tree);
440 next_item->address |= NODE_FLAG;
441 ksm_pages_sharing--;
442 } else {
443 rb_erase(&rmap_item->node, &root_stable_tree);
444 ksm_pages_shared--;
445 }
446 } else {
447 struct rmap_item *prev_item = rmap_item->prev;
448 462
449 BUG_ON(prev_item->next != rmap_item); 463 stable_node = rmap_item->head;
450 prev_item->next = next_item; 464 hlist_del(&rmap_item->hlist);
451 if (next_item) { 465 if (stable_node->hlist.first)
452 BUG_ON(next_item->prev != rmap_item);
453 next_item->prev = rmap_item->prev;
454 }
455 ksm_pages_sharing--; 466 ksm_pages_sharing--;
467 else {
468 rb_erase(&stable_node->node, &root_stable_tree);
469 free_stable_node(stable_node);
470 ksm_pages_shared--;
456 } 471 }
457 472
458 rmap_item->next = NULL;
459 rmap_item->address &= PAGE_MASK; 473 rmap_item->address &= PAGE_MASK;
460 474
461 } else if (rmap_item->address & NODE_FLAG) { 475 } else if (rmap_item->address & UNSTABLE_FLAG) {
462 unsigned char age; 476 unsigned char age;
463 /* 477 /*
464 * Usually ksmd can and must skip the rb_erase, because 478 * Usually ksmd can and must skip the rb_erase, because
@@ -859,31 +873,32 @@ up:
859 * This function checks if there is a page inside the stable tree 873 * This function checks if there is a page inside the stable tree
860 * with identical content to the page that we are scanning right now. 874 * with identical content to the page that we are scanning right now.
861 * 875 *
862 * This function return rmap_item pointer to the identical item if found, 876 * This function returns the stable tree node of identical content if found,
863 * NULL otherwise. 877 * NULL otherwise.
864 */ 878 */
865static struct rmap_item *stable_tree_search(struct page *page, 879static struct stable_node *stable_tree_search(struct page *page,
866 struct page **tree_pagep) 880 struct page **tree_pagep)
867{ 881{
868 struct rb_node *node = root_stable_tree.rb_node; 882 struct rb_node *node = root_stable_tree.rb_node;
883 struct stable_node *stable_node;
869 884
870 while (node) { 885 while (node) {
871 struct rmap_item *tree_rmap_item, *next_rmap_item; 886 struct hlist_node *hlist, *hnext;
887 struct rmap_item *tree_rmap_item;
872 struct page *tree_page; 888 struct page *tree_page;
873 int ret; 889 int ret;
874 890
875 tree_rmap_item = rb_entry(node, struct rmap_item, node); 891 stable_node = rb_entry(node, struct stable_node, node);
876 while (tree_rmap_item) { 892 hlist_for_each_entry_safe(tree_rmap_item, hlist, hnext,
893 &stable_node->hlist, hlist) {
877 BUG_ON(!in_stable_tree(tree_rmap_item)); 894 BUG_ON(!in_stable_tree(tree_rmap_item));
878 cond_resched(); 895 cond_resched();
879 tree_page = get_ksm_page(tree_rmap_item); 896 tree_page = get_ksm_page(tree_rmap_item);
880 if (tree_page) 897 if (tree_page)
881 break; 898 break;
882 next_rmap_item = tree_rmap_item->next;
883 remove_rmap_item_from_tree(tree_rmap_item); 899 remove_rmap_item_from_tree(tree_rmap_item);
884 tree_rmap_item = next_rmap_item;
885 } 900 }
886 if (!tree_rmap_item) 901 if (!hlist)
887 return NULL; 902 return NULL;
888 903
889 ret = memcmp_pages(page, tree_page); 904 ret = memcmp_pages(page, tree_page);
@@ -896,7 +911,7 @@ static struct rmap_item *stable_tree_search(struct page *page,
896 node = node->rb_right; 911 node = node->rb_right;
897 } else { 912 } else {
898 *tree_pagep = tree_page; 913 *tree_pagep = tree_page;
899 return tree_rmap_item; 914 return stable_node;
900 } 915 }
901 } 916 }
902 917
@@ -907,31 +922,32 @@ static struct rmap_item *stable_tree_search(struct page *page,
907 * stable_tree_insert - insert rmap_item pointing to new ksm page 922 * stable_tree_insert - insert rmap_item pointing to new ksm page
908 * into the stable tree. 923 * into the stable tree.
909 * 924 *
910 * This function returns rmap_item if success, NULL otherwise. 925 * This function returns the stable tree node just allocated on success,
926 * NULL otherwise.
911 */ 927 */
912static struct rmap_item *stable_tree_insert(struct page *kpage, 928static struct stable_node *stable_tree_insert(struct page *kpage)
913 struct rmap_item *rmap_item)
914{ 929{
915 struct rb_node **new = &root_stable_tree.rb_node; 930 struct rb_node **new = &root_stable_tree.rb_node;
916 struct rb_node *parent = NULL; 931 struct rb_node *parent = NULL;
932 struct stable_node *stable_node;
917 933
918 while (*new) { 934 while (*new) {
919 struct rmap_item *tree_rmap_item, *next_rmap_item; 935 struct hlist_node *hlist, *hnext;
936 struct rmap_item *tree_rmap_item;
920 struct page *tree_page; 937 struct page *tree_page;
921 int ret; 938 int ret;
922 939
923 tree_rmap_item = rb_entry(*new, struct rmap_item, node); 940 stable_node = rb_entry(*new, struct stable_node, node);
924 while (tree_rmap_item) { 941 hlist_for_each_entry_safe(tree_rmap_item, hlist, hnext,
942 &stable_node->hlist, hlist) {
925 BUG_ON(!in_stable_tree(tree_rmap_item)); 943 BUG_ON(!in_stable_tree(tree_rmap_item));
926 cond_resched(); 944 cond_resched();
927 tree_page = get_ksm_page(tree_rmap_item); 945 tree_page = get_ksm_page(tree_rmap_item);
928 if (tree_page) 946 if (tree_page)
929 break; 947 break;
930 next_rmap_item = tree_rmap_item->next;
931 remove_rmap_item_from_tree(tree_rmap_item); 948 remove_rmap_item_from_tree(tree_rmap_item);
932 tree_rmap_item = next_rmap_item;
933 } 949 }
934 if (!tree_rmap_item) 950 if (!hlist)
935 return NULL; 951 return NULL;
936 952
937 ret = memcmp_pages(kpage, tree_page); 953 ret = memcmp_pages(kpage, tree_page);
@@ -952,13 +968,16 @@ static struct rmap_item *stable_tree_insert(struct page *kpage,
952 } 968 }
953 } 969 }
954 970
955 rmap_item->address |= NODE_FLAG | STABLE_FLAG; 971 stable_node = alloc_stable_node();
956 rmap_item->next = NULL; 972 if (!stable_node)
957 rb_link_node(&rmap_item->node, parent, new); 973 return NULL;
958 rb_insert_color(&rmap_item->node, &root_stable_tree);
959 974
960 ksm_pages_shared++; 975 rb_link_node(&stable_node->node, parent, new);
961 return rmap_item; 976 rb_insert_color(&stable_node->node, &root_stable_tree);
977
978 INIT_HLIST_HEAD(&stable_node->hlist);
979
980 return stable_node;
962} 981}
963 982
964/* 983/*
@@ -1018,7 +1037,7 @@ struct rmap_item *unstable_tree_search_insert(struct rmap_item *rmap_item,
1018 } 1037 }
1019 } 1038 }
1020 1039
1021 rmap_item->address |= NODE_FLAG; 1040 rmap_item->address |= UNSTABLE_FLAG;
1022 rmap_item->address |= (ksm_scan.seqnr & SEQNR_MASK); 1041 rmap_item->address |= (ksm_scan.seqnr & SEQNR_MASK);
1023 rb_link_node(&rmap_item->node, parent, new); 1042 rb_link_node(&rmap_item->node, parent, new);
1024 rb_insert_color(&rmap_item->node, &root_unstable_tree); 1043 rb_insert_color(&rmap_item->node, &root_unstable_tree);
@@ -1033,18 +1052,16 @@ struct rmap_item *unstable_tree_search_insert(struct rmap_item *rmap_item,
1033 * the same ksm page. 1052 * the same ksm page.
1034 */ 1053 */
1035static void stable_tree_append(struct rmap_item *rmap_item, 1054static void stable_tree_append(struct rmap_item *rmap_item,
1036 struct rmap_item *tree_rmap_item) 1055 struct stable_node *stable_node)
1037{ 1056{
1038 rmap_item->next = tree_rmap_item->next; 1057 rmap_item->head = stable_node;
1039 rmap_item->prev = tree_rmap_item;
1040
1041 if (tree_rmap_item->next)
1042 tree_rmap_item->next->prev = rmap_item;
1043
1044 tree_rmap_item->next = rmap_item;
1045 rmap_item->address |= STABLE_FLAG; 1058 rmap_item->address |= STABLE_FLAG;
1059 hlist_add_head(&rmap_item->hlist, &stable_node->hlist);
1046 1060
1047 ksm_pages_sharing++; 1061 if (rmap_item->hlist.next)
1062 ksm_pages_sharing++;
1063 else
1064 ksm_pages_shared++;
1048} 1065}
1049 1066
1050/* 1067/*
@@ -1060,6 +1077,7 @@ static void cmp_and_merge_page(struct page *page, struct rmap_item *rmap_item)
1060{ 1077{
1061 struct rmap_item *tree_rmap_item; 1078 struct rmap_item *tree_rmap_item;
1062 struct page *tree_page = NULL; 1079 struct page *tree_page = NULL;
1080 struct stable_node *stable_node;
1063 struct page *kpage; 1081 struct page *kpage;
1064 unsigned int checksum; 1082 unsigned int checksum;
1065 int err; 1083 int err;
@@ -1067,8 +1085,8 @@ static void cmp_and_merge_page(struct page *page, struct rmap_item *rmap_item)
1067 remove_rmap_item_from_tree(rmap_item); 1085 remove_rmap_item_from_tree(rmap_item);
1068 1086
1069 /* We first start with searching the page inside the stable tree */ 1087 /* We first start with searching the page inside the stable tree */
1070 tree_rmap_item = stable_tree_search(page, &tree_page); 1088 stable_node = stable_tree_search(page, &tree_page);
1071 if (tree_rmap_item) { 1089 if (stable_node) {
1072 kpage = tree_page; 1090 kpage = tree_page;
1073 if (page == kpage) /* forked */ 1091 if (page == kpage) /* forked */
1074 err = 0; 1092 err = 0;
@@ -1080,7 +1098,7 @@ static void cmp_and_merge_page(struct page *page, struct rmap_item *rmap_item)
1080 * The page was successfully merged: 1098 * The page was successfully merged:
1081 * add its rmap_item to the stable tree. 1099 * add its rmap_item to the stable tree.
1082 */ 1100 */
1083 stable_tree_append(rmap_item, tree_rmap_item); 1101 stable_tree_append(rmap_item, stable_node);
1084 } 1102 }
1085 put_page(kpage); 1103 put_page(kpage);
1086 return; 1104 return;
@@ -1121,19 +1139,23 @@ static void cmp_and_merge_page(struct page *page, struct rmap_item *rmap_item)
1121 if (kpage) { 1139 if (kpage) {
1122 remove_rmap_item_from_tree(tree_rmap_item); 1140 remove_rmap_item_from_tree(tree_rmap_item);
1123 1141
1142 stable_node = stable_tree_insert(kpage);
1143 if (stable_node) {
1144 stable_tree_append(tree_rmap_item, stable_node);
1145 stable_tree_append(rmap_item, stable_node);
1146 }
1147 put_page(kpage);
1148
1124 /* 1149 /*
1125 * If we fail to insert the page into the stable tree, 1150 * If we fail to insert the page into the stable tree,
1126 * we will have 2 virtual addresses that are pointing 1151 * we will have 2 virtual addresses that are pointing
1127 * to a ksm page left outside the stable tree, 1152 * to a ksm page left outside the stable tree,
1128 * in which case we need to break_cow on both. 1153 * in which case we need to break_cow on both.
1129 */ 1154 */
1130 if (stable_tree_insert(kpage, tree_rmap_item)) 1155 if (!stable_node) {
1131 stable_tree_append(rmap_item, tree_rmap_item);
1132 else {
1133 break_cow(tree_rmap_item); 1156 break_cow(tree_rmap_item);
1134 break_cow(rmap_item); 1157 break_cow(rmap_item);
1135 } 1158 }
1136 put_page(kpage);
1137 } 1159 }
1138 } 1160 }
1139} 1161}