kernelnewbies.kernelnewbies.org archive mirror
 help / color / mirror / Atom feed
* kernel panic in sample block device driver
@ 2013-05-01  5:27 Kumar amit mehta
  2013-05-01 11:14 ` anish singh
  2013-05-01 16:54 ` Pranay Srivastava
  0 siblings, 2 replies; 4+ messages in thread
From: Kumar amit mehta @ 2013-05-01  5:27 UTC (permalink / raw)
  To: kernelnewbies

Hi,

I'm new to block layer in linux and to learn the same, I'm trying to
come up with a sample memory based block device driver, with which I can
experiment and learn along the way. I'm referring to sample code from
the linux tree [1] and assorted information available over the internet. 
My current module is causing system crash as soon I load it. Please take a
look.

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/blkdev.h>
#include <linux/fs.h>
/*
 * 1: register the major number
 * 2: register callback functions for various capabilities
 * 3: register a request function
 * 4: disks characteristics information; gendisk
 */

#define RAMDK_MAJOR	166 //unique but static on my current machine as of now	
#define BLKDEV_NAME	"ramdk"
#define RAMDK_MINOR_NR	1

#define DISKSIZE 256*1024 
#define NSECTORS 512
char buffer[DISKSIZE];

static struct gendisk *rdk = NULL;
static DEFINE_SPINLOCK(ramdk_sp_lock);
static struct request_queue *ramdk_queue = NULL;

int ramdk_open(struct block_device *, fmode_t);
int ramdk_release(struct gendisk *, fmode_t);

int ramdk_open(struct block_device *blk, fmode_t mode)
{
	printk(KERN_INFO "place holder for ramdisk's open method");
	return 0;
}

int ramdk_release(struct gendisk *gdk, fmode_t mode)
{
	printk(KERN_INFO "place holder for ramdisk's release method");
	return 0;
}
	
static const struct block_device_operations ramdk_op = {
	.owner = THIS_MODULE,
	.open = ramdk_open,
	.release = ramdk_release,
};

/*
 * block devices do not provide read()/write() routines like the char 
 * devices, instead they use request callback.
 */
static void rdk_request(struct request_queue *q)
{
	struct request *rq;

	/*
 	 * look at a request and then dequeue it
 	 */
	rq = blk_fetch_request(q);
	while (rq) {
		unsigned long offset = blk_rq_pos(rq);
		unsigned long nbytes  = blk_rq_cur_bytes(rq);
		int err = 0;
		while (nbytes) {
			if (rq_data_dir(rq) == READ) {
				memcpy(rq->buffer, (char *)offset, nbytes);
			} else if (rq_data_dir(rq) == WRITE) {
				memcpy((char *)offset, rq->buffer, nbytes);
			} else {
				printk(KERN_ERR "unknown operation\n");
			}
			nbytes -= offset;
		}
		if (!__blk_end_request_cur(rq, err))
			rq = blk_fetch_request(q);
	}
	return;
}

static int __init ramdk_init(void)
{
	int ret = -1;
	/*
 	 * blocking call. On success, assign an unused major number and add a entry in
 	 * /proc/devices.
 	 */
	if (register_blkdev(RAMDK_MAJOR, BLKDEV_NAME))
		return -EBUSY;

        printk(KERN_INFO "registered block device %s with major: %d", 
		BLKDEV_NAME, RAMDK_MAJOR);

	rdk = alloc_disk(RAMDK_MINOR_NR);
	if (!rdk) {
		ret = -ENOMEM;
		goto disk_alloc_fail;
	}

	rdk->fops = &ramdk_op;
	/*
 	 * HW perform I/O in the multiples of sectors(512Bytes, typically), whereas SW(FS, etc)
 	 * will work on block size(4k, typically). Therefore we need to tell the upper layers
 	 * about the capability of the hardware. This also sets the maximum number of sectors
 	 * that my hardware can receive per request.
 	 */
	set_capacity(rdk, DISKSIZE*2); //Capacity, in terms of sectors
	/*
         * returns request queue for the block device. protected using spin lock
         */
	ramdk_queue = blk_init_queue(rdk_request, &ramdk_sp_lock);
	if (!ramdk_queue)
		goto queue_fail;

	rdk->queue = ramdk_queue;   
	rdk->major = RAMDK_MAJOR;
	rdk->first_minor = 0;
	sprintf(rdk->disk_name, BLKDEV_NAME);
	rdk->private_data = buffer;
	/*
 	 * Going live now!!!
 	 */	
	add_disk(rdk);
	
	return 0;

queue_fail:
	printk(KERN_ERR "failed to allocate queue for %s",BLKDEV_NAME);

disk_alloc_fail:
	unregister_blkdev(RAMDK_MAJOR, BLKDEV_NAME);
	
	return ret;
}

static void __exit ramdk_exit(void)
{
        del_gendisk(rdk);
	put_disk(rdk);
   	blk_cleanup_queue(ramdk_queue);
	unregister_blkdev(RAMDK_MAJOR, BLKDEV_NAME); 
	printk(KERN_INFO "%s is offline now!!!",BLKDEV_NAME); 
}

module_init(ramdk_init);
module_exit(ramdk_exit);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("goon");

Once this issue is fixed, I plan to add support for filesystem related 
operations such as mkfs, mount, etc.

[1] drivers/block/z2ram.c

-Amit

^ permalink raw reply	[flat|nested] 4+ messages in thread

* kernel panic in sample block device driver
  2013-05-01  5:27 kernel panic in sample block device driver Kumar amit mehta
@ 2013-05-01 11:14 ` anish singh
  2013-05-01 16:54 ` Pranay Srivastava
  1 sibling, 0 replies; 4+ messages in thread
From: anish singh @ 2013-05-01 11:14 UTC (permalink / raw)
  To: kernelnewbies

kernel panic logs?


On Wed, May 1, 2013 at 10:57 AM, Kumar amit mehta <gmate.amit@gmail.com>wrote:

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

^ permalink raw reply	[flat|nested] 4+ messages in thread

* kernel panic in sample block device driver
  2013-05-01  5:27 kernel panic in sample block device driver Kumar amit mehta
  2013-05-01 11:14 ` anish singh
@ 2013-05-01 16:54 ` Pranay Srivastava
  2013-05-02  3:35   ` Kumar amit mehta
  1 sibling, 1 reply; 4+ messages in thread
From: Pranay Srivastava @ 2013-05-01 16:54 UTC (permalink / raw)
  To: kernelnewbies

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

Hey Amit,

I'm not sure about what's wrong with it, but why not try to process
each segment separately. i know it's more work but you should plan for
that too.
In the mean time you can look at

https://github.com/pranjas/block_driver

I wrote this sometime back and its commented heavily. its also for in
memory disk but you can set the block device sector size other than
512 bytes.

You might get a freeze kernel or crash when u unload it lemme know if
that happens, or change the blk_end_request call to
blk_end_request_all.

Hope it helps
                   -P.K.S


-- 
Pranay Srivastava

^ permalink raw reply	[flat|nested] 4+ messages in thread

* kernel panic in sample block device driver
  2013-05-01 16:54 ` Pranay Srivastava
@ 2013-05-02  3:35   ` Kumar amit mehta
  0 siblings, 0 replies; 4+ messages in thread
From: Kumar amit mehta @ 2013-05-02  3:35 UTC (permalink / raw)
  To: kernelnewbies

On Wed, May 01, 2013 at 10:24:40PM +0530, Pranay Srivastava wrote:
> https://github.com/pranjas/block_driver
>

Thank you so much, looks pretty heavy-duty right now though!!!

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2013-05-02  3:35 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-05-01  5:27 kernel panic in sample block device driver Kumar amit mehta
2013-05-01 11:14 ` anish singh
2013-05-01 16:54 ` Pranay Srivastava
2013-05-02  3:35   ` Kumar amit mehta

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).