Dear All, I am facing a problem while simulating a removable media via simple block driver. But if I remove the floppy disk after mounting it, I could not get any problem with the floppy disk. But I do not understand why I am facing the problem with my device. I prepared an IOCTL to simulate the removable media to the kernel. When the applications issues IOCTL, it removes the device from the kernel space. when I issue #ls /mnt (mount point) ( i.e. after the application issues the IOCTL) the CONSOLE crashes, OR it crashes when tried to unload the module. I have been trying hard to understand the real problem with this module. What wrong am I doing in this module? Could any body explain the problem? Thanks in advance. Thanks and Regards, Srinivas G Here is the module code for your reference. ------------------------------------------- /* * A sample, extra-simple block driver. * * Copyright 2003 Eklektix, Inc. Redistributable under the terms * of the GNU GPL. */ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/init.h> #include <linux/kernel.h> /* printk() */ #include <linux/fs.h> /* everything... */ #include <linux/errno.h> /* error codes */ #include <linux/types.h> /* size_t */ #include <linux/vmalloc.h> #include <linux/genhd.h> #include <linux/blkdev.h> #include <linux/hdreg.h> #include <linux/buffer_head.h> /* for invalidate_bdev */ #include "sbd_drv.h" MODULE_LICENSE("Dual BSD/GPL"); //static char *Version = "0.1"; static int major_num = 0; module_param(major_num, int, 0); static int hardsect_size = 512; module_param(hardsect_size, int, 0); static int nsectors = 1024; /* How big the drive is */ module_param(nsectors, int, 0); /* * We can tweak our hardware sector size, but the kernel talks to us * in terms of small sectors, always. */ #define KERNEL_SECTOR_SIZE 512 /* * Our request queue. */ static struct request_queue *Queue; /* * The internal representation of our device. */ static struct sbd_device { unsigned long size; spinlock_t lock; u8 *data; struct gendisk *gd; struct block_device *bdev; } Device; static int sbd_open(struct inode *inode, struct file *filp) { printk("<%s> invoked\n",__FUNCTION__); Device.bdev=inode->i_bdev; return 0; } static int sbd_close(struct inode *inode, struct file *filp) { printk("<%s> invoked\n",__FUNCTION__); Device.bdev=NULL; return 0; } /* * Handle an I/O request. */ static void sbd_transfer(struct sbd_device *dev, unsigned long sector, unsigned long nsect, char *buffer, int write) { unsigned long offset = sector*hardsect_size; unsigned long nbytes = nsect*hardsect_size; if ((offset + nbytes) > dev->size) { printk (KERN_NOTICE "sbd: Beyond-end write (%ld %ld)\n", offset, nbytes); return; } if (write) memcpy(dev->data + offset, buffer, nbytes); else memcpy(buffer, dev->data + offset, nbytes); } static void sbd_request(request_queue_t *q) { struct request *req; while ((req = elv_next_request(q)) != NULL) { if (! blk_fs_request(req)) { printk (KERN_NOTICE "Skip non-CMD request\n"); end_request(req, 0); continue; } sbd_transfer(&Device, req->sector, req->current_nr_sectors, req->buffer, rq_data_dir(req)); end_request(req, 1); } } /* * Ioctl. */ int sbd_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { long size; struct hd_geometry geo; switch(cmd) { /* * The only command we need to interpret is HDIO_GETGEO, since * we can't partition the drive otherwise. We have no real * geometry, of course, so make something up. */ case HDIO_GETGEO: size = Device.size*(hardsect_size/KERNEL_SECTOR_SIZE); geo.cylinders = (size & ~0x3f) >> 6; geo.heads = 4; geo.sectors = 16; geo.start = 4; if (copy_to_user((void *) arg, &geo, sizeof(geo))) return -EFAULT; return 0; case REMOVE_MOUNTED_DISK: if(Device.bdev) invalidate_bdev(Device.bdev,1); del_gendisk(Device.gd); put_disk(Device.gd); blk_cleanup_queue(Queue); vfree(Device.data); return 0; } return -ENOTTY; /* unknown command */ } /* * The device operations structure. */ static struct block_device_operations sbd_ops = { .owner = THIS_MODULE, .ioctl = sbd_ioctl, .open = sbd_open, .release = sbd_close }; static int __init sbd_init(void) { printk("<%s> invoked\n",__FUNCTION__); /* * Set up our internal device. */ Device.size = nsectors*hardsect_size; spin_lock_init(&Device.lock); Device.data = vmalloc(Device.size); if (Device.data == NULL) return -ENOMEM; /* * Get a request queue. */ Queue = blk_init_queue(sbd_request, &Device.lock); if (Queue == NULL) goto out; blk_queue_hardsect_size(Queue, hardsect_size); /* * Get registered. */ major_num = register_blkdev(major_num, "sbd"); if (major_num <= 0) { printk(KERN_WARNING "sbd: unable to get major number\n"); goto out; } /* * And the gendisk structure. */ Device.gd = alloc_disk(16); if (! Device.gd) goto out_unregister; Device.gd->major = major_num; Device.gd->first_minor = 0; Device.gd->fops = &sbd_ops; Device.gd->private_data = &Device; strcpy (Device.gd->disk_name, "sbd0"); set_capacity(Device.gd, nsectors*(hardsect_size/KERNEL_SECTOR_SIZE)); Device.gd->queue = Queue; add_disk(Device.gd); return 0; out_unregister: unregister_blkdev(major_num, "sbd"); out: vfree(Device.data); return -ENOMEM; } static void __exit sbd_exit(void) { printk("<%s> invoked\n",__FUNCTION__); del_gendisk(Device.gd); put_disk(Device.gd); unregister_blkdev(major_num, "sbd"); blk_cleanup_queue(Queue); vfree(Device.data); } module_init(sbd_init); module_exit(sbd_exit); ************************************************************************ *** .h file ------- include <asm/ioctl.h> #define SBD_MAJOR 'b' #define REMOVE_MOUNTED_DISK _IO(SBD_MAJOR,0x01) ************************************************************************ *** Makefile -------- # # Makefile for the simple hello world program # Author: Srinivas G. Date: 17th April 2006 # DEVICE:=sbd MAJOR:=230 KDIR:=/lib/modules/$(shell uname -r)/build TRGT:=sbd OBJS:=sbd_drv.o obj-m += $(TRGT).o $(TRGT)-objs := $(OBJS) default: $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules clean: $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) clean ************************************************************************ *** app.c file to issue an IOCTL ---------------------------- #include <fcntl.h> #include <stdio.h> #include "sbd_drv.h" main() { int fd; fd = open("/dev/sbd0",O_RDONLY); if(fd == -1) { printf("Open failed\n"); exit(0); } ioctl(fd,REMOVE_MOUNTED_DISK); close(fd); } ------------------------------------------------------------------------ --- -- Kernelnewbies: Help each other learn about the Linux kernel. Archive: http://mail.nl.linux.org/kernelnewbies/ FAQ: http://kernelnewbies.org/faq/