curious
curious

Reputation: 85

Linux Block Filter Driver

I have a basic linux block filter driver (taken from https://github.com/asimkadav/block-filter ) which i want to extend to do the following:

  1. Record IO pattern on device
  2. Duplicate IO to another device

I am trying to add to debugging info to "misc_request_fn" function but the kernel keep crashing.

I am not sure what i am doing wrong. further more - how can i identify write operation and duplicate it to another device ?

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

Upvotes: 1

Views: 1931

Answers (1)

NightWatchMan
NightWatchMan

Reputation: 45

Replace the below line from your code

blkdev = lookup_bdev(path);

and use,

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

This should fix the kernel reboot problem.

Upvotes: 1

Related Questions