On 5/1/13, Kumar amit mehta <gmate.amit@xxxxxxxxx> 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@xxxxxxxxxxxxxxxxx > 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 _______________________________________________ Kernelnewbies mailing list Kernelnewbies@xxxxxxxxxxxxxxxxx http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies