Wrapper device driver - hangs

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

 



Hi,

  We've written a simple wrapper device driver( linux kernel 2.6). This sample driver program creates an wrapper device to an underlying block device. 
i.e this driver will create an virtual device on top of the underlying disk - Open( ) of this driver will open the underlying disk, simillarly make_request + release.

After configuring/mapping the wrapper device to the underlying disk, any I/O operations done on the wrapper device will (internally) reflect on the underlying disk.

When configured, we are able to mount the device node (/dev/ourdtc) and do read-write operations to the disk.  Also, when mounted with -r option, we are able to do IO amd unmount it properly.

But when mounted with rw option, we are facing some issues like

1. We are able to perform I/O immediatly after mount. But, Unmount simply hangs. The stack shows submit_bh( ) has reported bug during buffer_mapped( ).

2. Also, if no I/O is not immediately after mounting(within few mins), then any write operation(like cp command) on the device, simply hangs.

We are migrating our application from 2.4 to 2.6 kernel. We are stuck up with this issue and not finding any clues on how to debug this.
Code snippet is given below:

So, please throw some light on this.

Thanks,

#define LOCAL_MAJ 253 /*change it to the major number of any underlying partition*/
#define LOCAL_MIN 5  /*change it to the minor number of the underlying partition*/

ftd_blk_open(struct inode *inode, struct file *filp)
{
..local = MKDEV(LOCAL_MAJ, LOCAL_MIN);
        bdev = bdget(local);
        blkdev_get(bdev, FMODE_READ|FMODE_WRITE, 0);
        if (!bdev->bd_disk->fops || !bdev->bd_disk->fops->open) ..
printk(KERN_ALERT "blk_open:error in !fops->open\n");
            err = ENOTTY;
        }
        else {
            old_fs = get_fs();
        set_fs(KERNEL_DS);
        bdev->bd_disk->fops->open(bdev->bd_inode, filp);
        set_fs(old_fs);
        }
        blkdev_put(bdev);..return err;
}

ftd_blk_release(struct inode *inode, struct file *filp)
{...
set_fs(KERNEL_DS);
        bdev->bd_disk->fops->release(bdev->bd_inode, filp);
        set_fs(old_fs);
.....}




static int hello_init(void)
{
static int ret;
int mkret;
        ret = register_blkdev(ftd_bmajor, "myftd");
        if (ret < 0) {
                printk(KERN_ALERT "ftd_init: can't get major %d\n", ftd_bmajor);
                printk(KERN_ALERT "ftd_init: return value = %d\n", ret);
                return (-1);
        }
        ftd_bmajor = ret;
        bd =  kmalloc(sizeof(struct block_device), GFP_KERNEL);
        memset(bd, 0, sizeof(struct block_device));
        bd->bd_disk = alloc_disk(1);
        if (!bd->bd_disk) {
          printk(KERN_ALERT "alloc_disk failed\n");
          return(-1);
        }
        bd->bd_disk->major = ftd_bmajor;
        bd->bd_disk->first_minor = 1;
strcpy(bd->bd_disk->disk_name, "myftd");
        bd->bd_disk->queue = blk_alloc_queue(GFP_KERNEL);
        if (bd->bd_disk->queue == NULL) {
                printk(KERN_ALERT "queue alloc failed\n");
                return (-1);
        }
        blk_queue_make_request(bd->bd_disk->queue, ftd_make_request);
        mkret = devfs_mk_dir ("myftd");
        if (mkret) {
          printk(KERN_ALERT "make dir failed\n");
          return (-1);
        }
        bd->bd_disk->fops = &ftd_bdops;
        blk_queue_hardsect_size(bd->bd_disk->queue, 512);
        set_capacity(bd->bd_disk, 0);
        add_disk(bd->bd_disk);
return 0;
}


static void hello_exit(void)
{
del_gendisk(bd->bd_disk);
put_disk(bd->bd_disk);
unregister_blkdev(ftd_bmajor, "myftd");
}




[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux