Linux块过滤驱动程序

时间:2017-02-02 21:09:50

标签: c linux linux-kernel linux-device-driver block

我有一个基本的linux块过滤器驱动程序(取自https://github.com/asimkadav/block-filter),我想扩展它以执行以下操作:

  1. 在设备上记录IO模式
  2. 将IO复制到另一台设备
  3. 我试图将调试信息添加到“misc_request_fn”函数,但内核不断崩溃。

    我不确定我做错了什么。 更多 - 我如何识别写操作并将其复制到另一个设备?

    #include <linux/pci.h>
    #include <linux/bug.h>
    #include <linux/kallsyms.h>
    #include <linux/kernel.h>
    #include <linux/module.h>
    #include <linux/rtnetlink.h>
    #include <linux/lockdep.h>
    #include <linux/slab.h>
    #include <linux/highmem.h>
    #include <linux/swap.h>
    #include <linux/completion.h>
    #include <linux/kthread.h>
    #include <linux/delay.h>
    #include <linux/blkdev.h>
    
    #ifndef _MISCDEVICE_H
    #define _MISCDEVICE_H
    
    // Driver number
    #define MISC_MINOR      45
    
    
    // Fault injection op-codes
    //
    #define MISC_GET 0x101
    #define MISC_PUT 0x102
    
    #endif
    
    
    
    static struct miscdevice misc_help;
    static struct block_device *blkdev;
    static void (*original_request_fn) (struct request_queue*, struct bio*);
    
    
    /* Sample ioctl code - not used. Can be used to trigger on/off filtering. */
    static long mischelp_ioctl(/*struct inode *inode,*/ struct file *fp,
                    unsigned int cmd, unsigned long arg) {
    
            if (cmd == MISC_GET)    {
                    printk ("Can perform get ops %d.\n", (int) arg);
            }
    
            if (cmd == MISC_PUT)    {
                    printk ("Can perform put ops %d.\n", (int) arg);
            }
    
            return 0;
    }
    
    
    struct file_operations misc_fops = {
            .unlocked_ioctl = mischelp_ioctl,
            .owner = THIS_MODULE,
            .mmap = NULL,
    };
    
    void misc_request_fn(struct request_queue *q, struct bio *bio) {
            //printk ("we are passing bios.\n");
            // here is where we trace requests...
            printk ("IO size %d\n",bio->bi_size);
            original_request_fn (q, bio);
            return;
    }
    
    
    void register_block_device(char *path)  {
    
            struct request_queue *blkdev_queue = NULL;
    
            if (path == NULL)       {
                    printk ("Block device empty.\n");
                    return;
            }
    
            printk ("Will open %s.\n", path);
    
            blkdev = lookup_bdev(path);
    
            if (IS_ERR(blkdev))     {
                    printk ("No such block device.\n");
                    return;
            }
    
            printk ("Found block device %p with bs %d.\n", blkdev, blkdev->bd_block_size);
            blkdev_queue = bdev_get_queue(blkdev);
            original_request_fn = blkdev_queue->request_fn;
            blkdev_queue->request_fn = misc_request_fn;
    }
    
    void unregister_block_device(void)      {
            struct request_queue *blkdev_queue = NULL;
    
            blkdev_queue = bdev_get_queue(blkdev);
    
            if ((blkdev_queue->request_fn != NULL) &&
                            (original_request_fn != NULL))  {
    
                    blkdev_queue->request_fn = original_request_fn;
                    printk ("Successfully unregistered block device.\n");
            }
    }
    
    
    
    int init_module(void)   {
            int retval = 0;
            static char *mischelp_name = "mischelp";
    
            misc_help.minor = MISC_MINOR;
            misc_help.name = mischelp_name;
            misc_help.fops = &misc_fops;
            retval = misc_register(&misc_help);
    
            if (retval)
                    return retval;
    
            register_block_device("/dev/sdg");
    
            printk ("block tracer initialized successfully.\n");
            return 0;
    }
    
    void cleanup_module(void){
            int number = 0;
    
            unregister_block_device();
    
            number = misc_deregister(&misc_help);
            if (number < 0) {
                    printk ("misc_deregister failed. %d\n", number);
            }
    
            printk ("It's over for block tracer.. \n");
    }
    

1 个答案:

答案 0 :(得分:1)

从代码中替换以下行

blkdev = lookup_bdev(路径);

并使用,

blkdev = blkdev_get_by_path(path,FMODE_READ | FMODE_WRITE,NULL);

这应解决内核重启问题。