diff options
author | Dave Chinner <david@fromorbit.com> | 2010-01-12 01:39:16 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-01-13 00:02:00 -0500 |
commit | 2c761270d5520dd84ab0b4e47c24d99ff8503c38 (patch) | |
tree | c23a51fdcc96641661b632d3b3c2c46ad7e53a91 /fs | |
parent | dbf004d7883b3adb058c0c1a5635bc4ec27651c0 (diff) |
lib: Introduce generic list_sort function
There are two copies of list_sort() in the tree already, one in the DRM
code, another in ubifs. Now XFS needs this as well. Create a generic
list_sort() function from the ubifs version and convert existing users
to it so we don't end up with yet another copy in the tree.
Signed-off-by: Dave Chinner <david@fromorbit.com>
Acked-by: Dave Airlie <airlied@redhat.com>
Acked-by: Artem Bityutskiy <dedekind@infradead.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ubifs/gc.c | 96 |
1 files changed, 1 insertions, 95 deletions
diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c index 618c2701d3a7..e5a3d8e96bb7 100644 --- a/fs/ubifs/gc.c +++ b/fs/ubifs/gc.c | |||
@@ -54,6 +54,7 @@ | |||
54 | */ | 54 | */ |
55 | 55 | ||
56 | #include <linux/pagemap.h> | 56 | #include <linux/pagemap.h> |
57 | #include <linux/list_sort.h> | ||
57 | #include "ubifs.h" | 58 | #include "ubifs.h" |
58 | 59 | ||
59 | /* | 60 | /* |
@@ -108,101 +109,6 @@ static int switch_gc_head(struct ubifs_info *c) | |||
108 | } | 109 | } |
109 | 110 | ||
110 | /** | 111 | /** |
111 | * list_sort - sort a list. | ||
112 | * @priv: private data, passed to @cmp | ||
113 | * @head: the list to sort | ||
114 | * @cmp: the elements comparison function | ||
115 | * | ||
116 | * This function has been implemented by Mark J Roberts <mjr@znex.org>. It | ||
117 | * implements "merge sort" which has O(nlog(n)) complexity. The list is sorted | ||
118 | * in ascending order. | ||
119 | * | ||
120 | * The comparison function @cmp is supposed to return a negative value if @a is | ||
121 | * than @b, and a positive value if @a is greater than @b. If @a and @b are | ||
122 | * equivalent, then it does not matter what this function returns. | ||
123 | */ | ||
124 | static void list_sort(void *priv, struct list_head *head, | ||
125 | int (*cmp)(void *priv, struct list_head *a, | ||
126 | struct list_head *b)) | ||
127 | { | ||
128 | struct list_head *p, *q, *e, *list, *tail, *oldhead; | ||
129 | int insize, nmerges, psize, qsize, i; | ||
130 | |||
131 | if (list_empty(head)) | ||
132 | return; | ||
133 | |||
134 | list = head->next; | ||
135 | list_del(head); | ||
136 | insize = 1; | ||
137 | for (;;) { | ||
138 | p = oldhead = list; | ||
139 | list = tail = NULL; | ||
140 | nmerges = 0; | ||
141 | |||
142 | while (p) { | ||
143 | nmerges++; | ||
144 | q = p; | ||
145 | psize = 0; | ||
146 | for (i = 0; i < insize; i++) { | ||
147 | psize++; | ||
148 | q = q->next == oldhead ? NULL : q->next; | ||
149 | if (!q) | ||
150 | break; | ||
151 | } | ||
152 | |||
153 | qsize = insize; | ||
154 | while (psize > 0 || (qsize > 0 && q)) { | ||
155 | if (!psize) { | ||
156 | e = q; | ||
157 | q = q->next; | ||
158 | qsize--; | ||
159 | if (q == oldhead) | ||
160 | q = NULL; | ||
161 | } else if (!qsize || !q) { | ||
162 | e = p; | ||
163 | p = p->next; | ||
164 | psize--; | ||
165 | if (p == oldhead) | ||
166 | p = NULL; | ||
167 | } else if (cmp(priv, p, q) <= 0) { | ||
168 | e = p; | ||
169 | p = p->next; | ||
170 | psize--; | ||
171 | if (p == oldhead) | ||
172 | p = NULL; | ||
173 | } else { | ||
174 | e = q; | ||
175 | q = q->next; | ||
176 | qsize--; | ||
177 | if (q == oldhead) | ||
178 | q = NULL; | ||
179 | } | ||
180 | if (tail) | ||
181 | tail->next = e; | ||
182 | else | ||
183 | list = e; | ||
184 | e->prev = tail; | ||
185 | tail = e; | ||
186 | } | ||
187 | p = q; | ||
188 | } | ||
189 | |||
190 | tail->next = list; | ||
191 | list->prev = tail; | ||
192 | |||
193 | if (nmerges <= 1) | ||
194 | break; | ||
195 | |||
196 | insize *= 2; | ||
197 | } | ||
198 | |||
199 | head->next = list; | ||
200 | head->prev = list->prev; | ||
201 | list->prev->next = head; | ||
202 | list->prev = head; | ||
203 | } | ||
204 | |||
205 | /** | ||
206 | * data_nodes_cmp - compare 2 data nodes. | 112 | * data_nodes_cmp - compare 2 data nodes. |
207 | * @priv: UBIFS file-system description object | 113 | * @priv: UBIFS file-system description object |
208 | * @a: first data node | 114 | * @a: first data node |