+ for (i = 0; i < limit; i++)
+ if (test_bit(bitmap, i))
+ count++;
+ return count;
+}
+
+static bool out_of_bounds(unsigned long off,
+ unsigned long pagesize,
+ unsigned long poolsize)
+{
+ return (off > poolsize || off + pagesize > poolsize);
+}
+
+static bool check_bucket(struct header *head,
+ unsigned long poolsize,
+ unsigned long pages[],
+ struct bucket_state *bs,
+ unsigned int bindex)
+{
+ bool lp_bucket = large_page_bucket(bindex, poolsize);
+ struct page_header *ph;
+ unsigned long taken, i, prev, pagesize, sp_bits, lp_bits;
+
+ lp_bits = large_page_bits(poolsize);
+ sp_bits = lp_bits - BITS_FROM_SMALL_TO_LARGE_PAGE;
+
+ pagesize = 1UL << (lp_bucket ? lp_bits : sp_bits);
+
+ /* This many elements fit? */
+ taken = page_header_size(bindex / INTER_BUCKET_SPACE,
+ bs->elements_per_page);
+ taken += bucket_to_size(bindex) * bs->elements_per_page;
+ if (taken > pagesize)
+ return check_fail();
+
+ /* One more wouldn't fit? */
+ taken = page_header_size(bindex / INTER_BUCKET_SPACE,
+ bs->elements_per_page + 1);
+ taken += bucket_to_size(bindex) * (bs->elements_per_page + 1);
+ if (taken <= pagesize)
+ return check_fail();
+
+ /* Walk used list. */
+ prev = 0;
+ for (i = bs->page_list; i; i = ph->next) {
+ /* Bad pointer? */
+ if (out_of_bounds(i, pagesize, poolsize))
+ return check_fail();
+ /* Wrong size page? */
+ if (!!test_bit(head->pagesize, i >> lp_bits) != lp_bucket)
+ return check_fail();
+ /* Not page boundary? */
+ if (i % pagesize)
+ return check_fail();
+ ph = from_off(head, i);
+ /* Linked list corrupt? */
+ if (ph->prev != prev)
+ return check_fail();
+ /* Already seen this page? */
+ if (test_bit(pages, i >> sp_bits))
+ return check_fail();
+ set_bit(pages, i >> sp_bits);
+ /* Empty or full? */
+ if (ph->elements_used == 0)
+ return check_fail();
+ if (ph->elements_used >= bs->elements_per_page)
+ return check_fail();
+ /* Used bits don't agree? */
+ if (ph->elements_used != count_bits(ph->used,
+ bs->elements_per_page))
+ return check_fail();
+ /* Wrong bucket? */
+ if (ph->bucket != bindex)
+ return check_fail();
+ prev = i;