diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/bitmap.c | 16 | ||||
-rw-r--r-- | lib/bitrev.c | 3 | ||||
-rw-r--r-- | lib/div64.c | 10 | ||||
-rw-r--r-- | lib/hexdump.c | 7 | ||||
-rw-r--r-- | lib/lmb.c | 46 | ||||
-rw-r--r-- | lib/parser.c | 32 | ||||
-rw-r--r-- | lib/radix-tree.c | 120 |
7 files changed, 130 insertions, 104 deletions
diff --git a/lib/bitmap.c b/lib/bitmap.c index c4cb48f77f0c..482df94ea21e 100644 --- a/lib/bitmap.c +++ b/lib/bitmap.c @@ -316,22 +316,6 @@ int bitmap_scnprintf(char *buf, unsigned int buflen, EXPORT_SYMBOL(bitmap_scnprintf); /** - * bitmap_scnprintf_len - return buffer length needed to convert - * bitmap to an ASCII hex string. - * @len: number of bits to be converted - */ -int bitmap_scnprintf_len(unsigned int len) -{ - /* we need 9 chars per word for 32 bit words (8 hexdigits + sep/null) */ - int bitslen = ALIGN(len, CHUNKSZ); - int wordlen = CHUNKSZ / 4; - int buflen = (bitslen / wordlen) * (wordlen + 1) * sizeof(char); - - return buflen; -} -EXPORT_SYMBOL(bitmap_scnprintf_len); - -/** * __bitmap_parse - convert an ASCII hex string into a bitmap. * @buf: pointer to buffer containing string. * @buflen: buffer size in bytes. If string is smaller than this diff --git a/lib/bitrev.c b/lib/bitrev.c index 989aff73f881..3956203456d4 100644 --- a/lib/bitrev.c +++ b/lib/bitrev.c @@ -42,10 +42,11 @@ const u8 byte_rev_table[256] = { }; EXPORT_SYMBOL_GPL(byte_rev_table); -static __always_inline u16 bitrev16(u16 x) +u16 bitrev16(u16 x) { return (bitrev8(x & 0xff) << 8) | bitrev8(x >> 8); } +EXPORT_SYMBOL(bitrev16); /** * bitrev32 - reverse the order of bits in a u32 value diff --git a/lib/div64.c b/lib/div64.c index bb5bd0c0f030..a111eb8de9cf 100644 --- a/lib/div64.c +++ b/lib/div64.c @@ -98,3 +98,13 @@ EXPORT_SYMBOL(div64_u64); #endif #endif /* BITS_PER_LONG == 32 */ + +/* + * Iterative div/mod for use when dividend is not expected to be much + * bigger than divisor. + */ +u32 iter_div_u64_rem(u64 dividend, u32 divisor, u64 *remainder) +{ + return __iter_div_u64_rem(dividend, divisor, remainder); +} +EXPORT_SYMBOL(iter_div_u64_rem); diff --git a/lib/hexdump.c b/lib/hexdump.c index 343546550dc9..f07c0db81d26 100644 --- a/lib/hexdump.c +++ b/lib/hexdump.c @@ -12,6 +12,9 @@ #include <linux/kernel.h> #include <linux/module.h> +const char hex_asc[] = "0123456789abcdef"; +EXPORT_SYMBOL(hex_asc); + /** * hex_dump_to_buffer - convert a blob of data to "hex ASCII" in memory * @buf: data blob to dump @@ -93,8 +96,8 @@ void hex_dump_to_buffer(const void *buf, size_t len, int rowsize, for (j = 0; (j < rowsize) && (j < len) && (lx + 4) < linebuflen; j++) { ch = ptr[j]; - linebuf[lx++] = hex_asc(ch >> 4); - linebuf[lx++] = hex_asc(ch & 0x0f); + linebuf[lx++] = hex_asc_hi(ch); + linebuf[lx++] = hex_asc_lo(ch); linebuf[lx++] = ' '; } ascii_column = 3 * rowsize + 2; diff --git a/lib/lmb.c b/lib/lmb.c index 83287d3869a3..5d7b9286503e 100644 --- a/lib/lmb.c +++ b/lib/lmb.c @@ -19,31 +19,43 @@ struct lmb lmb; +static int lmb_debug; + +static int __init early_lmb(char *p) +{ + if (p && strstr(p, "debug")) + lmb_debug = 1; + return 0; +} +early_param("lmb", early_lmb); + void lmb_dump_all(void) { -#ifdef DEBUG unsigned long i; - pr_debug("lmb_dump_all:\n"); - pr_debug(" memory.cnt = 0x%lx\n", lmb.memory.cnt); - pr_debug(" memory.size = 0x%llx\n", + if (!lmb_debug) + return; + + pr_info("lmb_dump_all:\n"); + pr_info(" memory.cnt = 0x%lx\n", lmb.memory.cnt); + pr_info(" memory.size = 0x%llx\n", (unsigned long long)lmb.memory.size); for (i=0; i < lmb.memory.cnt ;i++) { - pr_debug(" memory.region[0x%x].base = 0x%llx\n", + pr_info(" memory.region[0x%lx].base = 0x%llx\n", i, (unsigned long long)lmb.memory.region[i].base); - pr_debug(" .size = 0x%llx\n", + pr_info(" .size = 0x%llx\n", (unsigned long long)lmb.memory.region[i].size); } - pr_debug(" reserved.cnt = 0x%lx\n", lmb.reserved.cnt); - pr_debug(" reserved.size = 0x%lx\n", lmb.reserved.size); + pr_info(" reserved.cnt = 0x%lx\n", lmb.reserved.cnt); + pr_info(" reserved.size = 0x%llx\n", + (unsigned long long)lmb.memory.size); for (i=0; i < lmb.reserved.cnt ;i++) { - pr_debug(" reserved.region[0x%x].base = 0x%llx\n", + pr_info(" reserved.region[0x%lx].base = 0x%llx\n", i, (unsigned long long)lmb.reserved.region[i].base); - pr_debug(" .size = 0x%llx\n", + pr_info(" .size = 0x%llx\n", (unsigned long long)lmb.reserved.region[i].size); } -#endif /* DEBUG */ } static unsigned long lmb_addrs_overlap(u64 base1, u64 size1, u64 base2, @@ -286,8 +298,7 @@ static u64 __init lmb_alloc_nid_unreserved(u64 start, u64 end, j = lmb_overlaps_region(&lmb.reserved, base, size); if (j < 0) { /* this area isn't reserved, take it */ - if (lmb_add_region(&lmb.reserved, base, - lmb_align_up(size, align)) < 0) + if (lmb_add_region(&lmb.reserved, base, size) < 0) base = ~(u64)0; return base; } @@ -333,6 +344,10 @@ u64 __init lmb_alloc_nid(u64 size, u64 align, int nid, struct lmb_region *mem = &lmb.memory; int i; + BUG_ON(0 == size); + + size = lmb_align_up(size, align); + for (i = 0; i < mem->cnt; i++) { u64 ret = lmb_alloc_nid_region(&mem->region[i], nid_range, @@ -370,6 +385,8 @@ u64 __init __lmb_alloc_base(u64 size, u64 align, u64 max_addr) BUG_ON(0 == size); + size = lmb_align_up(size, align); + /* On some platforms, make sure we allocate lowmem */ /* Note that LMB_REAL_LIMIT may be LMB_ALLOC_ANYWHERE */ if (max_addr == LMB_ALLOC_ANYWHERE) @@ -393,8 +410,7 @@ u64 __init __lmb_alloc_base(u64 size, u64 align, u64 max_addr) j = lmb_overlaps_region(&lmb.reserved, base, size); if (j < 0) { /* this area isn't reserved, take it */ - if (lmb_add_region(&lmb.reserved, base, - lmb_align_up(size, align)) < 0) + if (lmb_add_region(&lmb.reserved, base, size) < 0) return 0; return base; } diff --git a/lib/parser.c b/lib/parser.c index 703c8c13b346..4f0cbc03e0e8 100644 --- a/lib/parser.c +++ b/lib/parser.c @@ -182,18 +182,25 @@ int match_hex(substring_t *s, int *result) } /** - * match_strcpy: - copies the characters from a substring_t to a string - * @to: string to copy characters to. - * @s: &substring_t to copy + * match_strlcpy: - Copy the characters from a substring_t to a sized buffer + * @dest: where to copy to + * @src: &substring_t to copy + * @size: size of destination buffer * - * Description: Copies the set of characters represented by the given - * &substring_t @s to the c-style string @to. Caller guarantees that @to is - * large enough to hold the characters of @s. + * Description: Copy the characters in &substring_t @src to the + * c-style string @dest. Copy no more than @size - 1 characters, plus + * the terminating NUL. Return length of @src. */ -void match_strcpy(char *to, const substring_t *s) +size_t match_strlcpy(char *dest, const substring_t *src, size_t size) { - memcpy(to, s->from, s->to - s->from); - to[s->to - s->from] = '\0'; + size_t ret = src->to - src->from; + + if (size) { + size_t len = ret >= size ? size - 1 : ret; + memcpy(dest, src->from, len); + dest[len] = '\0'; + } + return ret; } /** @@ -206,9 +213,10 @@ void match_strcpy(char *to, const substring_t *s) */ char *match_strdup(const substring_t *s) { - char *p = kmalloc(s->to - s->from + 1, GFP_KERNEL); + size_t sz = s->to - s->from + 1; + char *p = kmalloc(sz, GFP_KERNEL); if (p) - match_strcpy(p, s); + match_strlcpy(p, s, sz); return p; } @@ -216,5 +224,5 @@ EXPORT_SYMBOL(match_token); EXPORT_SYMBOL(match_int); EXPORT_SYMBOL(match_octal); EXPORT_SYMBOL(match_hex); -EXPORT_SYMBOL(match_strcpy); +EXPORT_SYMBOL(match_strlcpy); EXPORT_SYMBOL(match_strdup); diff --git a/lib/radix-tree.c b/lib/radix-tree.c index bd521716ab1a..169a2f8dabcc 100644 --- a/lib/radix-tree.c +++ b/lib/radix-tree.c @@ -88,6 +88,57 @@ static inline gfp_t root_gfp_mask(struct radix_tree_root *root) return root->gfp_mask & __GFP_BITS_MASK; } +static inline void tag_set(struct radix_tree_node *node, unsigned int tag, + int offset) +{ + __set_bit(offset, node->tags[tag]); +} + +static inline void tag_clear(struct radix_tree_node *node, unsigned int tag, + int offset) +{ + __clear_bit(offset, node->tags[tag]); +} + +static inline int tag_get(struct radix_tree_node *node, unsigned int tag, + int offset) +{ + return test_bit(offset, node->tags[tag]); +} + +static inline void root_tag_set(struct radix_tree_root *root, unsigned int tag) +{ + root->gfp_mask |= (__force gfp_t)(1 << (tag + __GFP_BITS_SHIFT)); +} + +static inline void root_tag_clear(struct radix_tree_root *root, unsigned int tag) +{ + root->gfp_mask &= (__force gfp_t)~(1 << (tag + __GFP_BITS_SHIFT)); +} + +static inline void root_tag_clear_all(struct radix_tree_root *root) +{ + root->gfp_mask &= __GFP_BITS_MASK; +} + +static inline int root_tag_get(struct radix_tree_root *root, unsigned int tag) +{ + return (__force unsigned)root->gfp_mask & (1 << (tag + __GFP_BITS_SHIFT)); +} + +/* + * Returns 1 if any slot in the node has this tag set. + * Otherwise returns 0. + */ +static inline int any_tag_set(struct radix_tree_node *node, unsigned int tag) +{ + int idx; + for (idx = 0; idx < RADIX_TREE_TAG_LONGS; idx++) { + if (node->tags[tag][idx]) + return 1; + } + return 0; +} /* * This assumes that the caller has performed appropriate preallocation, and * that the caller has pinned this thread of control to the current CPU. @@ -124,6 +175,17 @@ static void radix_tree_node_rcu_free(struct rcu_head *head) { struct radix_tree_node *node = container_of(head, struct radix_tree_node, rcu_head); + + /* + * must only free zeroed nodes into the slab. radix_tree_shrink + * can leave us with a non-NULL entry in the first slot, so clear + * that here to make sure. + */ + tag_clear(node, 0, 0); + tag_clear(node, 1, 0); + node->slots[0] = NULL; + node->count = 0; + kmem_cache_free(radix_tree_node_cachep, node); } @@ -165,59 +227,6 @@ out: } EXPORT_SYMBOL(radix_tree_preload); -static inline void tag_set(struct radix_tree_node *node, unsigned int tag, - int offset) -{ - __set_bit(offset, node->tags[tag]); -} - -static inline void tag_clear(struct radix_tree_node *node, unsigned int tag, - int offset) -{ - __clear_bit(offset, node->tags[tag]); -} - -static inline int tag_get(struct radix_tree_node *node, unsigned int tag, - int offset) -{ - return test_bit(offset, node->tags[tag]); -} - -static inline void root_tag_set(struct radix_tree_root *root, unsigned int tag) -{ - root->gfp_mask |= (__force gfp_t)(1 << (tag + __GFP_BITS_SHIFT)); -} - - -static inline void root_tag_clear(struct radix_tree_root *root, unsigned int tag) -{ - root->gfp_mask &= (__force gfp_t)~(1 << (tag + __GFP_BITS_SHIFT)); -} - -static inline void root_tag_clear_all(struct radix_tree_root *root) -{ - root->gfp_mask &= __GFP_BITS_MASK; -} - -static inline int root_tag_get(struct radix_tree_root *root, unsigned int tag) -{ - return (__force unsigned)root->gfp_mask & (1 << (tag + __GFP_BITS_SHIFT)); -} - -/* - * Returns 1 if any slot in the node has this tag set. - * Otherwise returns 0. - */ -static inline int any_tag_set(struct radix_tree_node *node, unsigned int tag) -{ - int idx; - for (idx = 0; idx < RADIX_TREE_TAG_LONGS; idx++) { - if (node->tags[tag][idx]) - return 1; - } - return 0; -} - /* * Return the maximum key which can be store into a * radix tree with height HEIGHT. @@ -930,11 +939,6 @@ static inline void radix_tree_shrink(struct radix_tree_root *root) newptr = radix_tree_ptr_to_indirect(newptr); root->rnode = newptr; root->height--; - /* must only free zeroed nodes into the slab */ - tag_clear(to_free, 0, 0); - tag_clear(to_free, 1, 0); - to_free->slots[0] = NULL; - to_free->count = 0; radix_tree_node_free(to_free); } } |