然后要改的是申请和释放内存代码。 原先我们使用的是__get_free_page()和free_page()函数,这一对函数用来申请和释放一个页面。 这显然不能满足现在的要求,我们改用它们的大哥:__get_free_pages()和free_pages()。 它们的原型是: unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order); void free_pages(unsigned long addr, unsigned int order); 可以注意到与__get_free_page()和free_page()函数相比,他们多了个order参数,正是用于指定返回2的多少次幂个连续的页。 因此原先的free_diskmem()和alloc_diskmem()函数将改成以下这样: void free_diskmem(void) { int i; void *p;
for (i = 0; i < (SIMP_BLKDEV_BYTES + SIMP_BLKDEV_DATASEGSIZE - 1) >> SIMP_BLKDEV_DATASEGSHIFT; i++) { p = radix_tree_lookup(&simp_blkdev_data, i); radix_tree_delete(&simp_blkdev_data, i); /* free NULL is safe */ free_pages((unsigned long)p, SIMP_BLKDEV_DATASEGORDER); } }
int alloc_diskmem(void) { int ret; int i; void *p;
INIT_RADIX_TREE(&simp_blkdev_data, GFP_KERNEL);
for (i = 0; i < (SIMP_BLKDEV_BYTES + SIMP_BLKDEV_DATASEGSIZE - 1) >> SIMP_BLKDEV_DATASEGSHIFT; i++) { p = (void *)__get_free_pages(GFP_KERNEL, SIMP_BLKDEV_DATASEGORDER); if (!p) { ret = -ENOMEM; goto err_alloc; }
ret = radix_tree_insert(&simp_blkdev_data, i, p); if (IS_ERR_VALUE(ret)) goto err_radix_tree_insert; } return 0;
现在,我们的simp_blkdev_make_request()函数变成了这样: static int simp_blkdev_make_request(struct request_queue *q, struct bio *bio) { struct bio_vec *bvec; int i; unsigned long long dsk_offset;
然后我们试图找出module_param_named的参数中与unsigned long long对应的type来。 结果是:google了,没找到;看linux/include/linux/moduleparam.h了,还是没找到。 结论是:目前的linux(2.6.28)还不支持unsigned long long类型的模块参数。 更新一些的内核中会不会有是将来的事,尽快搞定这一章的功能却是现在面临的问题。
switch (unit) { case ‘g‘: case ‘G‘: simp_blkdev_bytes <<= 30; break; case ‘m‘: case ‘M‘: simp_blkdev_bytes <<= 20; break; case ‘k‘: case ‘K‘: simp_blkdev_bytes <<= 10; break; case ‘b‘: case ‘B‘: break; default: return -EINVAL; }
return 0; } 然后在simp_blkdev_init()中调用这个函数: ret = getparam(); if (IS_ERR_VALUE(ret)) goto err_getparam; 当然,err_getparam的位置读者应该能猜出来了。
这样一来,工作大概就完成了,让我们看看结果: 使用默认值: # insmod simp_blkdev.ko # fdisk /dev/simp_blkdev Device contains neither a valid DOS partition table, nor Sun, SGI or OSF disklabel Building a new DOS disklabel. Changes will remain in memory only, until you decide to write them. After that, of course, the previous content won‘t be recoverable.
Warning: invalid flag 0x0000 of partition table 4 will be corrected by w(rite)
Command (m for help): p
Disk /dev/simp_blkdev: 16 MB, 16777216 bytes 1 heads, 32 sectors/track, 1024 cylinders Units = cylinders of 32 * 512 = 16384 bytes
Device Boot Start End Blocks Id System
Command (m for help): q
# 设定成20M: # rmmod simp_blkdev # insmod simp_blkdev.ko size=20M # fdisk /dev/simp_blkdev Device contains neither a valid DOS partition table, nor Sun, SGI or OSF disklabel Building a new DOS disklabel. Changes will remain in memory only, until you decide to write them. After that, of course, the previous content won‘t be recoverable.
The number of cylinders for this disk is set to 1280. There is nothing wrong with that, but this is larger than 1024, and could in certain setups cause problems with: 1) software that runs at boot time (e.g., old versions of LILO) 2) booting and partitioning software from other OSs (e.g., DOS FDISK, OS/2 FDISK) Warning: invalid flag 0x0000 of partition table 4 will be corrected by w(rite)
Command (m for help): p
Disk /dev/simp_blkdev: 20 MB, 20971520 bytes 1 heads, 32 sectors/track, 1280 cylinders Units = cylinders of 32 * 512 = 16384 bytes
Device Boot Start End Blocks Id System
Command (m for help): q
# 变态一下,还是设定成20M,但用k作单位: # rmmod simp_blkdev # insmod simp_blkdev.ko size=20480k # fdisk /dev/simp_blkdev Device contains neither a valid DOS partition table, nor Sun, SGI or OSF disklabel Building a new DOS disklabel. Changes will remain in memory only, until you decide to write them. After that, of course, the previous content won‘t be recoverable.
The number of cylinders for this disk is set to 1280. There is nothing wrong with that, but this is larger than 1024, and could in certain setups cause problems with: 1) software that runs at boot time (e.g., old versions of LILO) 2) booting and partitioning software from other OSs (e.g., DOS FDISK, OS/2 FDISK) Warning: invalid flag 0x0000 of partition table 4 will be corrected by w(rite)
Command (m for help): p
Disk /dev/simp_blkdev: 20 MB, 20971520 bytes 1 heads, 32 sectors/track, 1280 cylinders Units = cylinders of 32 * 512 = 16384 bytes