kernelnewbies.kernelnewbies.org archive mirror
 help / color / mirror / Atom feed
* add_disk() make my driver's initialisation, thus kernel stall.
@ 2016-03-20  8:38 张云
  2016-03-20 22:18 ` Valdis.Kletnieks at vt.edu
  0 siblings, 1 reply; 5+ messages in thread
From: 张云 @ 2016-03-20  8:38 UTC (permalink / raw)
  To: kernelnewbies

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 = vmalloc(dev->size);
    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 = vmalloc(dev->size);
    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");
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.kernelnewbies.org/pipermail/kernelnewbies/attachments/20160320/c38d4d40/attachment-0001.html 

^ permalink raw reply	[flat|nested] 5+ messages in thread

* add_disk() make my driver's initialisation, thus kernel stall.
  2016-03-20  8:38 add_disk() make my driver's initialisation, thus kernel stall 张云
@ 2016-03-20 22:18 ` Valdis.Kletnieks at vt.edu
  2016-03-21  1:53   ` 回复:Re: " 张云
  0 siblings, 1 reply; 5+ messages in thread
From: Valdis.Kletnieks at vt.edu @ 2016-03-20 22:18 UTC (permalink / raw)
  To: kernelnewbies

On Sun, 20 Mar 2016 16:38:12 +0800, ?????? said:

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

> int major = 0;

Are you positive that this is both safe and usable?
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 848 bytes
Desc: not available
Url : http://lists.kernelnewbies.org/pipermail/kernelnewbies/attachments/20160320/fef2ff83/attachment.bin 

^ permalink raw reply	[flat|nested] 5+ messages in thread

* 回复:Re: add_disk() make my driver's initialisation, thus kernel stall.
  2016-03-20 22:18 ` Valdis.Kletnieks at vt.edu
@ 2016-03-21  1:53   ` 张云
  2016-03-21  2:55     ` Valdis.Kletnieks at vt.edu
  0 siblings, 1 reply; 5+ messages in thread
From: 张云 @ 2016-03-21  1:53 UTC (permalink / raw)
  To: kernelnewbies

The code is just for learning block driver


?? ??????
?2016?03?21? 06:18?valdis.kletnieks at vt.edu ??:
On Sun, 20 Mar 2016 16:38:12 +0800, ?? ??? said:

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

> int major = 0;

Are you positive that this is both safe and usable?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.kernelnewbies.org/pipermail/kernelnewbies/attachments/20160321/354a255d/attachment.html 

^ permalink raw reply	[flat|nested] 5+ messages in thread

* 回复:Re: add_disk() make my driver's initialisation,  thus kernel stall.
  2016-03-21  1:53   ` 回复:Re: " 张云
@ 2016-03-21  2:55     ` Valdis.Kletnieks at vt.edu
  2016-03-21  8:18       ` 张云
  0 siblings, 1 reply; 5+ messages in thread
From: Valdis.Kletnieks at vt.edu @ 2016-03-21  2:55 UTC (permalink / raw)
  To: kernelnewbies

On Mon, 21 Mar 2016 09:53:47 +0800, ?????? said:
> The code is just for learning block driver

THe kernel doesn't know that.  You call a routine with the wrong
parameters, it will not work properly.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 848 bytes
Desc: not available
Url : http://lists.kernelnewbies.org/pipermail/kernelnewbies/attachments/20160320/2894a5b8/attachment.bin 

^ permalink raw reply	[flat|nested] 5+ messages in thread

* add_disk() make my driver's initialisation, thus kernel stall.
  2016-03-21  2:55     ` Valdis.Kletnieks at vt.edu
@ 2016-03-21  8:18       ` 张云
  0 siblings, 0 replies; 5+ messages in thread
From: 张云 @ 2016-03-21  8:18 UTC (permalink / raw)
  To: kernelnewbies

Maybe I had misunderstood your meaning. 
You are meaning I have assign 0 to my device major number? 
The major variable is reassigned by the kernel in blkplay_init function.

http://stackoverflow.com/questions/13518404/add-disk-hangs-on-insmod <http://stackoverflow.com/questions/13518404/add-disk-hangs-on-insmod>
This post solve the problem.

Now, I can compile it, insmod it. But it?s give me a permission error when I open the device.

> On Mar 21, 2016, at 10:55 AM, Valdis.Kletnieks at vt.edu wrote:
> 
> On Mon, 21 Mar 2016 09:53:47 +0800, ?? said:
>> The code is just for learning block driver
> 
> THe kernel doesn't know that.  You call a routine with the wrong
> parameters, it will not work properly.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.kernelnewbies.org/pipermail/kernelnewbies/attachments/20160321/1a9d6c6f/attachment.html 

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2016-03-21  8:18 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-03-20  8:38 add_disk() make my driver's initialisation, thus kernel stall 张云
2016-03-20 22:18 ` Valdis.Kletnieks at vt.edu
2016-03-21  1:53   ` 回复:Re: " 张云
2016-03-21  2:55     ` Valdis.Kletnieks at vt.edu
2016-03-21  8:18       ` 张云

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).