Add a fsck symlink to btrfsck
[platform/upstream/btrfs-progs.git] / kernel-lib / list_sort.c
1 /*
2  * taken from linux kernel lib/list_sort.c, removed unneeded code and adapted
3  * for btrfsprogs
4  */
5
6 #include "kerncompat.h"
7 #include "list_sort.h"
8 #include "list.h"
9
10 #define MAX_LIST_LENGTH_BITS 20
11
12 /*
13  * Returns a list organized in an intermediate format suited
14  * to chaining of merge() calls: null-terminated, no reserved or
15  * sentinel head node, "prev" links not maintained.
16  */
17 static struct list_head *merge(void *priv,
18                                 int (*cmp)(void *priv, struct list_head *a,
19                                         struct list_head *b),
20                                 struct list_head *a, struct list_head *b)
21 {
22         struct list_head head, *tail = &head;
23
24         while (a && b) {
25                 /* if equal, take 'a' -- important for sort stability */
26                 if ((*cmp)(priv, a, b) <= 0) {
27                         tail->next = a;
28                         a = a->next;
29                 } else {
30                         tail->next = b;
31                         b = b->next;
32                 }
33                 tail = tail->next;
34         }
35         tail->next = a?:b;
36         return head.next;
37 }
38
39 /*
40  * Combine final list merge with restoration of standard doubly-linked
41  * list structure.  This approach duplicates code from merge(), but
42  * runs faster than the tidier alternatives of either a separate final
43  * prev-link restoration pass, or maintaining the prev links
44  * throughout.
45  */
46 static void merge_and_restore_back_links(void *priv,
47                                 int (*cmp)(void *priv, struct list_head *a,
48                                         struct list_head *b),
49                                 struct list_head *head,
50                                 struct list_head *a, struct list_head *b)
51 {
52         struct list_head *tail = head;
53
54         while (a && b) {
55                 /* if equal, take 'a' -- important for sort stability */
56                 if ((*cmp)(priv, a, b) <= 0) {
57                         tail->next = a;
58                         a->prev = tail;
59                         a = a->next;
60                 } else {
61                         tail->next = b;
62                         b->prev = tail;
63                         b = b->next;
64                 }
65                 tail = tail->next;
66         }
67         tail->next = a ? : b;
68
69         do {
70                 /*
71                  * In worst cases this loop may run many iterations.
72                  * Continue callbacks to the client even though no
73                  * element comparison is needed, so the client's cmp()
74                  * routine can invoke cond_resched() periodically.
75                  */
76                 (*cmp)(priv, tail->next, tail->next);
77
78                 tail->next->prev = tail;
79                 tail = tail->next;
80         } while (tail->next);
81
82         tail->next = head;
83         head->prev = tail;
84 }
85
86 /**
87  * list_sort - sort a list
88  * @priv: private data, opaque to list_sort(), passed to @cmp
89  * @head: the list to sort
90  * @cmp: the elements comparison function
91  *
92  * This function implements "merge sort", which has O(nlog(n))
93  * complexity.
94  *
95  * The comparison function @cmp must return a negative value if @a
96  * should sort before @b, and a positive value if @a should sort after
97  * @b. If @a and @b are equivalent, and their original relative
98  * ordering is to be preserved, @cmp must return 0.
99  */
100 void list_sort(void *priv, struct list_head *head,
101                 int (*cmp)(void *priv, struct list_head *a,
102                         struct list_head *b))
103 {
104         struct list_head *part[MAX_LIST_LENGTH_BITS+1]; /* sorted partial lists
105                                                 -- last slot is a sentinel */
106         int lev;  /* index into part[] */
107         int max_lev = 0;
108         struct list_head *list;
109
110         if (list_empty(head))
111                 return;
112
113         memset(part, 0, sizeof(part));
114
115         head->prev->next = NULL;
116         list = head->next;
117
118         while (list) {
119                 struct list_head *cur = list;
120                 list = list->next;
121                 cur->next = NULL;
122
123                 for (lev = 0; part[lev]; lev++) {
124                         cur = merge(priv, cmp, part[lev], cur);
125                         part[lev] = NULL;
126                 }
127                 if (lev > max_lev) {
128                         if (lev >= ARRAY_SIZE(part)-1) {
129                                 printf("list_sort: list passed to"
130                                         " list_sort() too long for"
131                                         " efficiency\n");
132                                 lev--;
133                         }
134                         max_lev = lev;
135                 }
136                 part[lev] = cur;
137         }
138
139         for (lev = 0; lev < max_lev; lev++)
140                 if (part[lev])
141                         list = merge(priv, cmp, part[lev], list);
142
143         merge_and_restore_back_links(priv, cmp, head, part[max_lev], list);
144 }