<div dir="ltr">kernel panic logs?</div><div class="gmail_extra"><br><br><div class="gmail_quote">On Wed, May 1, 2013 at 10:57 AM, Kumar amit mehta <span dir="ltr"><<a href="mailto:gmate.amit@gmail.com" target="_blank">gmate.amit@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi,<br>
<br>
I'm new to block layer in linux and to learn the same, I'm trying to<br>
come up with a sample memory based block device driver, with which I can<br>
experiment and learn along the way. I'm referring to sample code from<br>
the linux tree [1] and assorted information available over the internet.<br>
My current module is causing system crash as soon I load it. Please take a<br>
look.<br>
<br>
#include <linux/kernel.h><br>
#include <linux/module.h><br>
#include <linux/sched.h><br>
#include <linux/blkdev.h><br>
#include <linux/fs.h><br>
/*<br>
* 1: register the major number<br>
* 2: register callback functions for various capabilities<br>
* 3: register a request function<br>
* 4: disks characteristics information; gendisk<br>
*/<br>
<br>
#define RAMDK_MAJOR 166 //unique but static on my current machine as of now<br>
#define BLKDEV_NAME "ramdk"<br>
#define RAMDK_MINOR_NR 1<br>
<br>
#define DISKSIZE 256*1024<br>
#define NSECTORS 512<br>
char buffer[DISKSIZE];<br>
<br>
static struct gendisk *rdk = NULL;<br>
static DEFINE_SPINLOCK(ramdk_sp_lock);<br>
static struct request_queue *ramdk_queue = NULL;<br>
<br>
int ramdk_open(struct block_device *, fmode_t);<br>
int ramdk_release(struct gendisk *, fmode_t);<br>
<br>
int ramdk_open(struct block_device *blk, fmode_t mode)<br>
{<br>
printk(KERN_INFO "place holder for ramdisk's open method");<br>
return 0;<br>
}<br>
<br>
int ramdk_release(struct gendisk *gdk, fmode_t mode)<br>
{<br>
printk(KERN_INFO "place holder for ramdisk's release method");<br>
return 0;<br>
}<br>
<br>
static const struct block_device_operations ramdk_op = {<br>
.owner = THIS_MODULE,<br>
.open = ramdk_open,<br>
.release = ramdk_release,<br>
};<br>
<br>
/*<br>
* block devices do not provide read()/write() routines like the char<br>
* devices, instead they use request callback.<br>
*/<br>
static void rdk_request(struct request_queue *q)<br>
{<br>
struct request *rq;<br>
<br>
/*<br>
* look at a request and then dequeue it<br>
*/<br>
rq = blk_fetch_request(q);<br>
while (rq) {<br>
unsigned long offset = blk_rq_pos(rq);<br>
unsigned long nbytes = blk_rq_cur_bytes(rq);<br>
int err = 0;<br>
while (nbytes) {<br>
if (rq_data_dir(rq) == READ) {<br>
memcpy(rq->buffer, (char *)offset, nbytes);<br>
} else if (rq_data_dir(rq) == WRITE) {<br>
memcpy((char *)offset, rq->buffer, nbytes);<br>
} else {<br>
printk(KERN_ERR "unknown operation\n");<br>
}<br>
nbytes -= offset;<br>
}<br>
if (!__blk_end_request_cur(rq, err))<br>
rq = blk_fetch_request(q);<br>
}<br>
return;<br>
}<br>
<br>
static int __init ramdk_init(void)<br>
{<br>
int ret = -1;<br>
/*<br>
* blocking call. On success, assign an unused major number and add a entry in<br>
* /proc/devices.<br>
*/<br>
if (register_blkdev(RAMDK_MAJOR, BLKDEV_NAME))<br>
return -EBUSY;<br>
<br>
printk(KERN_INFO "registered block device %s with major: %d",<br>
BLKDEV_NAME, RAMDK_MAJOR);<br>
<br>
rdk = alloc_disk(RAMDK_MINOR_NR);<br>
if (!rdk) {<br>
ret = -ENOMEM;<br>
goto disk_alloc_fail;<br>
}<br>
<br>
rdk->fops = &ramdk_op;<br>
/*<br>
* HW perform I/O in the multiples of sectors(512Bytes, typically), whereas SW(FS, etc)<br>
* will work on block size(4k, typically). Therefore we need to tell the upper layers<br>
* about the capability of the hardware. This also sets the maximum number of sectors<br>
* that my hardware can receive per request.<br>
*/<br>
set_capacity(rdk, DISKSIZE*2); //Capacity, in terms of sectors<br>
/*<br>
* returns request queue for the block device. protected using spin lock<br>
*/<br>
ramdk_queue = blk_init_queue(rdk_request, &ramdk_sp_lock);<br>
if (!ramdk_queue)<br>
goto queue_fail;<br>
<br>
rdk->queue = ramdk_queue;<br>
rdk->major = RAMDK_MAJOR;<br>
rdk->first_minor = 0;<br>
sprintf(rdk->disk_name, BLKDEV_NAME);<br>
rdk->private_data = buffer;<br>
/*<br>
* Going live now!!!<br>
*/<br>
add_disk(rdk);<br>
<br>
return 0;<br>
<br>
queue_fail:<br>
printk(KERN_ERR "failed to allocate queue for %s",BLKDEV_NAME);<br>
<br>
disk_alloc_fail:<br>
unregister_blkdev(RAMDK_MAJOR, BLKDEV_NAME);<br>
<br>
return ret;<br>
}<br>
<br>
static void __exit ramdk_exit(void)<br>
{<br>
del_gendisk(rdk);<br>
put_disk(rdk);<br>
blk_cleanup_queue(ramdk_queue);<br>
unregister_blkdev(RAMDK_MAJOR, BLKDEV_NAME);<br>
printk(KERN_INFO "%s is offline now!!!",BLKDEV_NAME);<br>
}<br>
<br>
module_init(ramdk_init);<br>
module_exit(ramdk_exit);<br>
MODULE_LICENSE("GPL v2");<br>
MODULE_AUTHOR("goon");<br>
<br>
Once this issue is fixed, I plan to add support for filesystem related<br>
operations such as mkfs, mount, etc.<br>
<br>
[1] drivers/block/z2ram.c<br>
<br>
-Amit<br>
<br>
_______________________________________________<br>
Kernelnewbies mailing list<br>
<a href="mailto:Kernelnewbies@kernelnewbies.org">Kernelnewbies@kernelnewbies.org</a><br>
<a href="http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies" target="_blank">http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies</a><br>
</blockquote></div><br></div>