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

2016-03-21 Thread 张云
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 

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.kletni...@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.

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


Re: 回复:Re: add_disk() make my driver's initialisation, thus kernel stall.

2016-03-20 Thread Valdis . Kletnieks
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.


pgp60L5FwYLA3.pgp
Description: PGP signature
___
Kernelnewbies mailing list
Kernelnewbies@kernelnewbies.org
http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies


回复:Re: add_disk() make my driver's initialisation, thus kernel stall.

2016-03-20 Thread 张云
The code is just for learning block driver


发自 网易邮箱大师
在2016年03月21日 06:18,valdis.kletni...@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?
___
Kernelnewbies mailing list
Kernelnewbies@kernelnewbies.org
http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies


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

2016-03-20 Thread Valdis . Kletnieks
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?


pgpOvdXw4jw1a.pgp
Description: PGP signature
___
Kernelnewbies mailing list
Kernelnewbies@kernelnewbies.org
http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies


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

2016-03-20 Thread 张云
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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#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");
got