Модуль блочного устройства Linux зависает при выгрузке с помощью rmmod (del_gendisk) - PullRequest
0 голосов
/ 15 июня 2019

Я пишу небольшой пример для драйверов блочных устройств в Linux.Этот пример не завершен, и я делаю шаг за шагом.Я зарегистрировал блочное устройство с blkdev_register и выделил структуру gendisk с alloc_disk.Все отлично работает, при вставке модуля.Он отображается в / proc / devices .Но если я хочу выгрузить его с rmmod, он зависает.

Я выяснил, что в функции выгрузки модуля вызов del_gendisk вызвал зависание.Я знаю, что структура gendisk имеет встроенный kobject, который занимается подсчетом ссылок.Этот механизм мешает вам выгрузить модуль, пока он используется.Но поскольку я не вызываю add_disk, не должно быть ссылок на эту структуру.

#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/genhd.h>
#include <linux/blkdev.h>

#define BLKDEVNAME  "blkdev_test"
#define MINORS      16  

struct block_device_operations bdops = {
    .owner = THIS_MODULE
};

struct blkdev {
    int major;  
    struct gendisk *disk;
    struct request_queue *queue;
} dev;


static int __init blkdev_init(void)         
{                                                                   
    dev.major = register_blkdev( 0, BLKDEVNAME );   
    if( dev.major < 0 )
        return -EIO;

    dev.disk = alloc_disk(MINORS);
    if( dev.disk == NULL )
        goto DISK_ERR;

    dev.disk->major = dev.major;
    dev.disk->first_minor = 0;
    snprintf(dev.disk->disk_name, DISK_NAME_LEN, "bd0" ); 
    dev.disk->fops = &bdops;
    // dev.disk->queue = dev.queue;

    // add_disk( dev.disk );

    return 0;

DISK_ERR:
    unregister_blkdev( dev.major, BLKDEVNAME ); 
    return -EIO;
}

static void __exit blkdev_exit(void) 
{
    del_gendisk(dev.disk);  
    unregister_blkdev( dev.major, BLKDEVNAME );
}

module_init(blkdev_init);   
module_exit(blkdev_exit);
MODULE_LICENSE("GPL");

Если я введу команду sudo rmmod mod.ko, то команда будет уничтожена системой.

1 Ответ

0 голосов
/ 15 июня 2019

Цитирование :

Управление гендисками После того, как вы настроили свою структуру гендиска, вы должны добавить ее в список активных дисков;это делается с помощью:

void add_disk(struct gendisk *disk);

После этого вызова ваше устройство активно.Об add_disk () следует иметь в виду несколько вещей:

add_disk() can create I/O to the device (to read partition tables and such). You should not call add_disk() until your driver is
sufficiently initialized to handle requests.

If you are calling add_disk() in your driver initialization routine, you should not fail the initialization process after the
first call.

The call to add_disk() increments the disk's reference count; if the disk structure is ever to be released, the driver is responsible
for decrementing that count (with put_disk()). 

Если вам нужно удалить диск из системы, это выполняется с помощью:

void del_gendisk(struct gendisk *disk);

Эта функцияочищает всю информацию, связанную с данным диском, и обычно удаляет ее из системы.После вызова del_gendisk () больше операций не будет отправлено на данное устройство.Ссылка вашего драйвера на объект gendisk остается, однако;Вы должны явно освободить его с помощью:

void put_disk(struct gendisk *disk);

Этот вызов приведет к освобождению структуры gendisk, если ни одна другая часть ядра не сохранит ссылку на нее.

...