Simulating the REMOVABLE media - Could any one please suggest me.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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);
}
	
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux