LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Software > Linux - Kernel
User Name
Password
Linux - Kernel This forum is for all discussion relating to the Linux kernel.

Notices

Reply
 
Search this Thread
Old 04-16-2011, 12:35 PM   #1
eantoranz
Senior Member
 
Registered: Apr 2003
Location: Colombia
Distribution: Kubuntu, Debian, Knoppix
Posts: 1,982
Blog Entries: 1

Rep: Reputation: 83
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.
 
Old 04-16-2011, 08:33 PM   #2
eantoranz
Senior Member
 
Registered: Apr 2003
Location: Colombia
Distribution: Kubuntu, Debian, Knoppix
Posts: 1,982
Blog Entries: 1

Original Poster
Rep: Reputation: 83
I'm wondering.... is it possible that I create the node manually with mknod using the major number assigned to my block driver?
 
Old 04-17-2011, 11:24 AM   #3
bsat
Member
 
Registered: Feb 2009
Posts: 347

Rep: Reputation: 72
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) .
 
Old 04-17-2011, 12:12 PM   #4
eantoranz
Senior Member
 
Registered: Apr 2003
Location: Colombia
Distribution: Kubuntu, Debian, Knoppix
Posts: 1,982
Blog Entries: 1

Original Poster
Rep: Reputation: 83
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.
 
  


Reply

Tags
dev, ubuntu, uml


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
/dev/sdf and /dev/sdb special device cannot mount bloodyscript Linux - Newbie 2 02-28-2010 07:05 PM
block device file delet after reboot from /dev viral_Ahire Linux - Software 2 03-15-2008 08:43 AM
Missing Block Device /dev/hdc1 !?! whishkah Linux - Hardware 2 09-06-2006 09:31 AM
Block device /dev/sda3 is not a valid root device.. rincewind Linux - Hardware 7 06-09-2006 04:47 AM
special device /dev/cdrom does not exist anolan514 Linux - Newbie 1 11-14-2001 10:34 PM


All times are GMT -5. The time now is 09:01 PM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration