bitmap­_find_free_region and bitmap_full arg doubts

From: Komal Shah
Date: Thu Nov 30 2006 - 10:33:54 EST


Hi,

I was writing the test module, for layered bitmaps, specific to my
requirement such that I want to have control/track of 2GB virtual
address space. As per the discussion with Paul Mundt, I have taken the
approach of segmenting the virt. space with 128MB of blocks and then
to do find_next_zero_bit followed by bitmap_find_free_region on the
bitmaps.

I have attached the test module code. I have confusion about the what
to pass as second argument of bitmap_find_free_region for 2nd layer
bitmap.

Do we have to pass "total size of the block...here 128MB" as the
second argument or no. of bits in that block, which 32768 (128 >>
PAGE_SHIFT) ?

This confusion arised as store queue implementation (sq.c) of sh arch,
passes total size of the bitmap (64M) as the second argument instead
of bits.

Same is the case with bitmap_full, where I have to pass total size of
the block (here 128MB) instead of no. of bits, in-order it to make my
test module work correctly.

--
Link: sq.c
http://www.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;h=7bcc73f9b8df535ad8887383aeac71a8b2491ef5;hb=0215ffb08ce99e2bb59eca114a99499a4d06e704;f=arch/sh/kernel/cpu/sh4/sq.c

--
---Komal Shah
http://komalshah.blogspot.com
/* test module for layered bitmaps */

#include <linux/init.h>
#include <linux/module.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <asm/bitops.h>
#include <asm/sizes.h>

#define VIRT_SIZE SZ_2G
#define L1_BM_SEG_SIZE 0x8000000 /* 128MB */
#define L1_BM_NUM_SEGS (VIRT_SIZE / L1_BM_SEG_SIZE)
#define L1_BM_BITS L1_BM_NUM_SEGS /* 16 bits */

#define L2_BM_BITS (L1_BM_SEG_SIZE >> PAGE_SHIFT)
#define L2_BM_SIZE L1_BM_SEG_SIZE
#define L2_BM_LONGS ((L2_BM_BITS + BITS_PER_LONG - 1) / BITS_PER_LONG)

static unsigned long bm_l1 = 0x0000;
static unsigned long *bm_l2;
static unsigned long next_off = 0x0;

#define start_addr 0x80000000

static unsigned long test_find_free_region(unsigned long size)
{
int l1_off, l2_off;
unsigned long addr = 0x0;
unsigned int order;
unsigned long *tmp_bm;

if (size > L1_BM_SEG_SIZE) {
printk(KERN_ERR "size greater than 128MB is not allowed\n");
return -EINVAL;
}

order = get_order(size);

next_block:
l1_off = find_next_zero_bit(&bm_l1, L1_BM_BITS, next_off);
if (l1_off >= L1_BM_BITS) {
printk(KERN_ERR "layer1 bitmap is full\n");
return -EINVAL;
}

tmp_bm = bm_l2 + (l1_off * L2_BM_LONGS);
l2_off = bitmap_find_free_region(tmp_bm, 32768 /* L2_BM_SIZE */,
order);

printk(KERN_INFO "l1_off %d l2_off %d\n", l1_off, l2_off);
if (l2_off < 0) {
next_off = (l1_off >= L1_BM_BITS) ? 0 : (next_off + 1);
if (bitmap_full(tmp_bm, L2_BM_SIZE /*L2_BM_BITS*/)) {
set_bit(l1_off, &bm_l1);
}
printk(KERN_INFO "go to next_block %ld\n", next_off);
goto next_block;
}

if (bitmap_full(tmp_bm, L2_BM_SIZE /*L2_BM_BITS*/)) {
set_bit(l1_off, &bm_l1);
}

addr = (l1_off * L1_BM_SEG_SIZE) + (l2_off << PAGE_SHIFT);

return (addr + start_addr);
}

static int __init test_alloc_init(void)
{
/*required ulongs for storage of nr_bits */
unsigned int size = (L2_BM_BITS + (BITS_PER_LONG - 1)) / BITS_PER_LONG;
unsigned long addr;

/* sixteen 128MB layer 2 bitmaps */
bm_l2 = kzalloc(size * L1_BM_NUM_SEGS, GFP_KERNEL);
if (!bm_l2) {
printk(KERN_INFO "No memory...\n");
return -EINVAL;
}
addr = test_find_free_region(SZ_64M);
printk(KERN_INFO "addr is 0x%lx\n", addr);

addr = test_find_free_region(SZ_64M + SZ_32M);
printk(KERN_INFO "addr is 0x%lx\n", addr);

addr = test_find_free_region(SZ_128M);
printk(KERN_INFO "addr is 0x%lx\n", addr);

return 0;
}

static void __exit test_alloc_exit(void)
{
/* TODO: care to free allocations :) */
}

module_init(test_alloc_init);
module_exit(test_alloc_exit);
MODULE_LICENSE("GPL");