Reputation: 85
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:
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
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