LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Kernel (https://www.linuxquestions.org/questions/linux-kernel-70/)
-   -   Missing /dev/ special file after I register a block device (https://www.linuxquestions.org/questions/linux-kernel-70/missing-dev-special-file-after-i-register-a-block-device-875343/)

eantoranz 04-16-2011 12:35 PM

Missing /dev/ special file after I register a block device
 
Hi!

I'm working on a block device of my own. I'm playing with it inside UML (had to compile UML by hand in order to have module support) and I realized that when I load it, I don't get to see the /dev/ special file I create for it. Just in case, I revisited the sbull driver and it failed to create the special device as well... and then, just to make sure the problem is in UML, I tried loading the sbull driver on the UML host (ubuntu maverick) and the device does show up... so it's something in UML, right? What did I miss when I compiled it?

Thanks in advance.

Here's the sbull code I'm using:

Code:

/*
* Mini-block driver.
*
* Este código está basado en el ejemplo de LWN.NET: http://lwn.net/Articles/31513/
*
* Copyright 2003 Eklektix, Inc.  Redistributable under the terms
* of the GNU GPL.
*
* Actualizacion por parte de Edmundo Carmona <eantoranz@gmail.com>
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>
#include <linux/genhd.h>
#include <linux/blkdev.h>
#include <linux/hdreg.h>


MODULE_LICENSE("Dual BSD/GPL");

/*
* Algunos valores que podrian haber
* sido parametrizables.
*/
#define KERNEL_SECTOR_SIZE 512
#define MAJOR_NUM 240 /* un major number libre, segun devices.txt */
#define MINIBD_MINORS 16 /* numero de particiones posibles */
#define N_SECTORS 1024 /* el numero de sectores de nuestro block device */
#define MINIBLOCK_SECTOR_SIZE 512 /* nuestro tammanyo de sector */

/*
* La cola de peticiones del mini-block.
*/
static struct request_queue *miniblock_queue;

/*
* Representacion interna de nuestro device.
*/
static struct miniblock_device {
        unsigned long size;
        spinlock_t lock;
        u8 *data;
        struct gendisk *gd;
};

static struct miniblock_device *Miniblock = NULL;

/*
* Manipulacion real en nuestro dispositivo de las I/O request.
*/
static void miniblock_transfer(struct miniblock_device *dev, struct request * req)
{
    unsigned long offset = blk_rq_pos(req) * MINIBLOCK_SECTOR_SIZE;
    unsigned long nbytes = blk_rq_cur_sectors(req) * MINIBLOCK_SECTOR_SIZE;
    printk(KERN_ERR "minibd: desplazamiento peticion: %d tama\%o: %d\n", offset, nbytes);

    if ((offset + nbytes) > dev->size) {
        printk (KERN_NOTICE "minibd: escritura por encima del final (%ld %ld)\n", offset, nbytes);
        return;
    }
    if (rq_data_dir(req))
        memcpy(dev->data + offset, req->buffer, nbytes);
    else
        memcpy(req->buffer, dev->data + offset, nbytes);
}

/*
* Manipulacion de las I/O request.
*/
static void miniblock_request(struct request_queue *q)
{
    struct request *req;

    while ((req = blk_fetch_request(q)) != NULL) {
        if (!req->cmd_type != REQ_TYPE_FS) {
            printk (KERN_NOTICE "Skip non-CMD request\n");
            __blk_end_request_all(req, 0);
            continue;
        }
        miniblock_transfer(Miniblock, req);
        __blk_end_request_all(req, 1);
    }

}

/*
* Ioctls perosonalizadas para nuestro device.
*/
int miniblock_ioctl (struct inode *inode, struct file *filp,
                unsigned int cmd, unsigned long arg)
{
        long size;
        struct hd_geometry geo;

        switch(cmd) {
            case HDIO_GETGEO:
                size = Miniblock->size*(MINIBLOCK_SECTOR_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;
    }

    return -ENOTTY;
}

/*
* Operaciones asociadas a nuestro dispositivo.
*/
static struct block_device_operations miniblock_ops = {
    .owner          = THIS_MODULE,
    .ioctl          = miniblock_ioctl
};

/*
* Inicializacion del modulo.
*/
static int __init miniblock_init(void)
{
        static int ret;

        ret = register_blkdev(MAJOR_NUM, "minibd");
        if (ret < 0) {
                printk(KERN_WARNING "minibd: error en asignacion de major number\n");
                return -EBUSY;
        }

        printk(KERN_DEBUG "minibd: registrado con exito\n");

        Miniblock = kmalloc(sizeof(struct miniblock_device), GFP_KERNEL);
        if (Miniblock == NULL) {
                printk(KERN_WARNING "minidb: error asignando memoria con kmalloc\n");
                goto out_unregister;
        }

        /*
        * Inicializamos nuestro device.
        */
        memset(Miniblock, 0, sizeof(struct miniblock_device));
        Miniblock->size = N_SECTORS*MINIBLOCK_SECTOR_SIZE;
        Miniblock->data = vmalloc(Miniblock->size);
        if (Miniblock->data == NULL) {
                printk(KERN_WARNING "minidb: error asignando memoria con vmalloc\n");
                kfree(Miniblock);
                goto out_unregister;
        }
        spin_lock_init(&Miniblock->lock);

        /*
        * Creamos nuestra request queue asociada (una por block device).
        */
        miniblock_queue = blk_init_queue(miniblock_request, &Miniblock->lock);
        if (miniblock_queue == NULL) {
                printk(KERN_WARNING "minibd: error en blk_init_queue\n");
                goto out_free;
        }

        blk_queue_logical_block_size(miniblock_queue, MINIBLOCK_SECTOR_SIZE);

        /*
        * Rellenamos nuestra gendisk structure.
        */
        Miniblock->gd = alloc_disk(MINIBD_MINORS);
        if (!Miniblock->gd) {
                printk(KERN_WARNING "minibd: error en alloc_disk\n");
                goto out_free;
        }

        Miniblock->gd->major = MAJOR_NUM;
        Miniblock->gd->first_minor = 0;
        Miniblock->gd->fops = &miniblock_ops;
        Miniblock->gd->private_data = Miniblock;
        snprintf(Miniblock->gd->disk_name, 10, "%s", "minibd0");
        set_capacity(Miniblock->gd, N_SECTORS*(MINIBLOCK_SECTOR_SIZE/KERNEL_SECTOR_SIZE));
        Miniblock->gd->queue = miniblock_queue;

        add_disk(Miniblock->gd); // <- Here is where the registration takes place

        return 0;

out_free:
        vfree(Miniblock->data);
        kfree(Miniblock);
out_unregister:
        unregister_blkdev(MAJOR_NUM, "minibd");

        return -ENOMEM;
}

/*
* Descarga del modulo.
*/
static void __exit miniblock_exit(void)
{
        del_gendisk(Miniblock->gd);
        put_disk(Miniblock->gd);

        unregister_blkdev(MAJOR_NUM, "minibd");
        blk_cleanup_queue(miniblock_queue);

        vfree(Miniblock->data);
        kfree(Miniblock);

        printk(KERN_DEBUG "minibd: descargado con exito\n");
}

module_init(miniblock_init);
module_exit(miniblock_exit);

Thanks in advance.

eantoranz 04-16-2011 08:33 PM

I'm wondering.... is it possible that I create the node manually with mknod using the major number assigned to my block driver?

bsat 04-17-2011 11:24 AM

Am just taking a wild guess you might have already tried this.
from your code it seems you are allocating the major number statically(240) may be you can check if the number is already being used by some other driver.

regarding second post, if you are asking can we created the special files ourselves using mknod manually, then yes we sure can ( you will have to be root) .

eantoranz 04-17-2011 12:12 PM

Well, my other driver (the one I'm doing the real work on) is asking for the major number to be assigned by the kernel... and the device fails to be created there as well... so it's not because the major could be taken.

Also, I tried with mknod and apparently it works... I still have a lot to learn before I'm able to do something useful from the block layer API.

Thanks for your reply.


All times are GMT -5. The time now is 12:50 AM.