add_disk() make my driver's initialisation, thus kernel stall.

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

 



Hi,

My memory disk block driver was compiled successfully.
But when I insmod my module, initialisation stall at add_disk  in setup_dev function.

What’s wrong with my gendisk setup code?
Thanks.

static void setup_dev(struct blkplay_dev *dev, int which)
{
    // setup disk size
    memset(dev, 0, sizeof(struct blkplay_dev));
    dev->size = nsectors * hardsect_size;
    dev->data = "">
    if (dev->data == NULL) {
        printk(KERN_NOTICE "vmalloc failure.\n");
        return;
    }

    // init request queue
    spin_lock_init(&dev->lock);

    dev->queue = blk_init_queue(blkplay_request, &dev->lock);
    if (dev->queue == NULL) {
        printk(KERN_NOTICE "init queue failure.\n");
        goto out_vfree;
    }

    //blk_queue_logical_block_size(dev->queue, hardsect_size);
    dev->queue->queuedata = dev;

    dev->gd = alloc_disk(BLKPLAY_MINORS);
    if (!dev->gd) {
        printk(KERN_NOTICE "alloc_disk failure!\n");
        goto out_vfree;
    }

    dev->gd->major = major;
    dev->gd->first_minor = which * BLKPLAY_MINORS;
    dev->gd->fops = &blkplay_ops;
    dev->gd->queue = dev->queue;
    dev->gd->private_data = dev;
    snprintf(dev->gd->disk_name, 32, "blkplay%c", which + 'a');
    set_capacity(dev->gd, nsectors * (hardsect_size/KERNEL_SECTOR_SIZE));

printk(KERN_ALERT "5\n”);

// *********************************************
// initialisation stall at the statement below.
// *********************************************
    add_disk(dev->gd);

printk(KERN_ALERT "6\n");

    return;

out_vfree:
    if (dev->data)
        vfree(dev->data); 
}




The whole module code:


#include <linux/module.h>

#include <linux/init.h>

#include <linux/blkdev.h>

#include <linux/genhd.h>

#include <linux/bio.h>

#include <linux/kernel.h>

#include <linux/slab.h>

#include <linux/vmalloc.h>


#include "debug.h"


#define BLKPLAY_MINORS 16

#define KERNEL_SECTOR_SIZE 512

#define DEVICE_NUMBER   1


int major = 0;

int nsectors = 1024;

int hardsect_size = 512;


static const char *module_name = "blkplay";


struct blkplay_dev {

    int size;

    uint8_t *data;

    spinlock_t lock;

    struct request_queue *queue;

    struct gendisk *gd;

};


struct blkplay_dev * devices;


    

int blkplay_open(struct block_device *dev, fmode_t mode)

{

    return 0;

}


void blkplay_release(struct gendisk *disk, fmode_t mode)

{

}


/*

 * Handle an I/O request.

 */

static void blkplay_transfer(struct blkplay_dev *dev, unsigned long sector, unsigned long nsect, char *buffer, int write)

{

unsigned long offset = sector*KERNEL_SECTOR_SIZE;

unsigned long nbytes = nsect*KERNEL_SECTOR_SIZE;


if ((offset + nbytes) > dev->size) {

printk (KERN_NOTICE "Beyond-end write (%ld %ld)\n", offset, nbytes);

return;

}

if (write)

memcpy(dev->data + offset, buffer, nbytes);

else

memcpy(buffer, dev->data + offset, nbytes);

}


/*

 * Transfer a single BIO.

 */

static int vmem_disk_xfer_bio(struct blkplay_dev *dev, struct bio *bio)

{

    struct bio_vec bvec;

    struct bvec_iter iter;

    sector_t sector = bio->bi_iter.bi_sector;


    bio_for_each_segment(bvec, bio, iter) {

        char *buffer = __bio_kmap_atomic(bio, iter);

        blkplay_transfer(dev, sector, bio_cur_bytes(bio) >> 9,

            buffer, bio_data_dir(bio) == WRITE);

        sector += bio_cur_bytes(bio) >> 9;

        __bio_kunmap_atomic(buffer);

    }

    return 0;

}

void blkplay_request(struct request_queue *q)

{

    struct request *req;

    struct bio *bio;


    while (!blk_queue_stopped(q) && 

            (req = blk_peek_request(q)) != NULL) {

        struct blkplay_dev *dev = req->rq_disk->private_data;

        blk_start_request(req);

        if (req->cmd_type != REQ_TYPE_FS) {

            printk (KERN_NOTICE "Skip non-fs request\n");

            blk_end_request_all(req, -EIO);

            continue;

        }

    

        __rq_for_each_bio(bio, req)

            vmem_disk_xfer_bio(dev, bio);

        blk_end_request_all(req, 0);

    }

}


const struct block_device_operations blkplay_ops = {

    //.owner = THIS_MODULE,

    //.open = blkplay_open,

    //.release = blkplay_release,

};


static void release_dev(struct blkplay_dev *dev)

{

    del_gendisk(dev->gd);

    put_disk(dev->gd);

    blk_cleanup_queue(dev->queue);

    vfree(dev->data);

}

static void setup_dev(struct blkplay_dev *dev, int which)

{

    // setup disk size

    memset(dev, 0, sizeof(struct blkplay_dev));

    dev->size = nsectors * hardsect_size;

    dev->data = "">

    if (dev->data == NULL) {

        printk(KERN_NOTICE "vmalloc failure.\n");

        return;

    }


    // init request queue

    spin_lock_init(&dev->lock);


    dev->queue = blk_init_queue(blkplay_request, &dev->lock);

    if (dev->queue == NULL) {

        printk(KERN_NOTICE "init queue failure.\n");

        goto out_vfree;

    }


    //blk_queue_logical_block_size(dev->queue, hardsect_size);

    dev->queue->queuedata = dev;


    dev->gd = alloc_disk(BLKPLAY_MINORS);

    if (!dev->gd) {

        printk(KERN_NOTICE "alloc_disk failure!\n");

        goto out_vfree;

    }


    dev->gd->major = major;

    dev->gd->first_minor = which * BLKPLAY_MINORS;

    dev->gd->fops = &blkplay_ops;

    dev->gd->queue = dev->queue;

    dev->gd->private_data = dev;

    snprintf(dev->gd->disk_name, 32, "blkplay%c", which + 'a');

    set_capacity(dev->gd, nsectors * (hardsect_size/KERNEL_SECTOR_SIZE));


printk(KERN_ALERT "5\n");

    add_disk(dev->gd);

printk(KERN_ALERT "6\n");


    return;


out_vfree:

    if (dev->data)

        vfree(dev->data); 

}


static int __init blkplay_init(void)

{

    int i;


    int ret;

    major = register_blkdev(major, module_name);

    if (0 >= major )

    {

        goto reg_blkplay_fail;

    } else {

        printk(KERN_ALERT "Allocate major number %d\n", major);

    }

    PDEBUG("Init success!\n");


    devices = kmalloc(DEVICE_NUMBER * sizeof(struct blkplay_dev), GFP_KERNEL);

    if (devices == NULL) {

        printk(KERN_ALERT "Allocate memory for devices failure.\n");

    }


    for (i = 0; i < DEVICE_NUMBER; i++)

    {

        printk(KERN_ALERT "Set up device for %d\n", i);

        setup_dev(devices + i, i);

    }

    return 0;


reg_blkplay_fail:

    PDEBUG("Init Error!\n");

    return ret;

}


static void __exit blkplay_exit(void)

{

    int i;

    for (i = 0; i < DEVICE_NUMBER; i++)

    {

        release_dev(&devices[i]);

    }

    unregister_blkdev(major, module_name);

    kfree(devices);

    PDEBUG("Exit.\n");

}


module_init(blkplay_init);

module_exit(blkplay_exit);


MODULE_LICENSE("Dual GPL/BSD");

_______________________________________________
Kernelnewbies mailing list
Kernelnewbies@xxxxxxxxxxxxxxxxx
http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies

[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