LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 06-24-2015, 08:14 AM   #1
DoubleHead
LQ Newbie
 
Registered: Jun 2015
Posts: 2

Rep: Reputation: Disabled
Problem with block device filter (make_request_fn)


Hello!

Im new in kernel modules development, and try to make simple block device filter. And have a two little questions

I've changed make_request_fn() with my own function (see my code below). I've digged source codes of read() etc and now I expect, my function must be called for all request (read and write) . But in my virtualbox with Centos7(3.10), I see my function work only for writes and not for reads. Could anyone say where I was wrong?

And next one - I can get request data from bio_data, but how I can determine the size of this data buffer? Is b->bi_size correct field to get this size?

Code:
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/blkdev.h>
#include <linux/buffer_head.h>
#define PARTITION_NAME "/dev/sdb"


char *ptr;
int i;
struct block_device *bd;
make_request_fn *orig_mrqfn;
 
static void filter_mrqfn(struct request_queue *rq, struct bio *b)
{
	printk(KERN_INFO "filter: Sector=lu Size=%d bi_rw=%lu\n", b->bi_sector, b->bi_size, b->bi_rw);

	ptr=(char *)bio_data(b);
	for(i=0;i<b->bi_size;i++)  //4096 as bio is going to be in 4kb chunk?????
	{
	   printk("%c",*ptr);
	   ptr++;
	}


	orig_mrqfn(rq, b); /* calling the original make_request_fn() */
}
 

/*
* set_mrqfn() - Change the original make_request_fn() to our
* modules request function
*/
static void set_mrqfn(void)
{
	struct super_block *sb;
	printk(KERN_DEBUG "filter: %s\n", __FUNCTION__);
	/* lock filesystem to prevent any further changes */
	fsync_bdev(bd);
	sb = freeze_bdev(bd);
	if (bd->bd_disk->queue->make_request_fn == filter_mrqfn) {
		printk(KERN_INFO "filter: modules request function is already active\n");
	} else {
		/* save the pointer to the original make_request_fn() */
		orig_mrqfn = bd->bd_disk->queue->make_request_fn;
		/* replace the original with our modules request function */
		bd->bd_disk->queue->make_request_fn = filter_mrqfn;
	}
	
	/* unlock filesystem */
	thaw_bdev(bd, sb);
}

/*
* restore_mrqfn() - Restore the original make_request_fn()
*/
static void restore_mrqfn(void)
{
	struct super_block *sb = bd->bd_super;
	printk(KERN_DEBUG "filter: %s\n", __FUNCTION__);
	if (orig_mrqfn) {
		/* lock filesystem to prevent any further changes */
		fsync_bdev(bd);
		sb = freeze_bdev(bd);
		/* restore the original request function */
		bd->bd_disk->queue->make_request_fn = orig_mrqfn;
		/* unlock filesystem */
		thaw_bdev(bd, sb);
	}
	orig_mrqfn = NULL;
}

static int __init filter_init(void)
{
	printk(KERN_DEBUG "filter: %s\n", __FUNCTION__);
	orig_mrqfn = NULL;
	// Read block device from path
	bd = blkdev_get_by_path(PARTITION_NAME, FMODE_READ, NULL);
	if (IS_ERR(bd)) {
		printk(KERN_ERR "filter: failed to get block device\n");
		return 0;
	}
	
	printk(KERN_INFO "filter: found block device with major number %d\n", bd->bd_disk->major);
	printk(KERN_INFO "filter: file system block size %d\n", bd->bd_block_size);
	printk(KERN_INFO "filter: start sector %lu\n", (unsigned long)bd->bd_part->start_sect);
	printk(KERN_INFO "filter: number of sectors %lu\n", (unsigned long)bd->bd_part->nr_sects);
	printk(KERN_INFO "filter: logical block size %d\n", bdev_logical_block_size(bd));
	printk(KERN_INFO "filter: physical block size %d\n", bdev_physical_block_size(bd));
	set_mrqfn();
	return 0;
}

static void __exit filter_exit(void)
{
	printk(KERN_DEBUG "filter: %s\n", __FUNCTION__);
	restore_mrqfn();
	if (!IS_ERR(bd)) {
		blkdev_put(bd, FMODE_READ);
	}
}

module_init(filter_init);
module_exit(filter_exit);
MODULE_LICENSE("Dual MIT/GPL");
MODULE_AUTHOR("Me");
With best regards,
Vasily

Last edited by DoubleHead; 06-24-2015 at 11:04 AM.
 
Old 06-25-2015, 03:30 PM   #2
smallpond
Senior Member
 
Registered: Feb 2011
Location: Massachusetts, USA
Distribution: Fedora
Posts: 4,149

Rep: Reputation: 1264Reputation: 1264Reputation: 1264Reputation: 1264Reputation: 1264Reputation: 1264Reputation: 1264Reputation: 1264Reputation: 1264
read and write transfer data between user space and kernel block cache. Neither go through your function.

The request queue is between block cache and disk I/O, after things like elevator sort, write coalescing, etc.

The read did not trigger a request if the data is in cache.

Writes may be delayed and combined, so you will see fewer writes than were issued by user space.
 
Old 06-25-2015, 03:39 PM   #3
DoubleHead
LQ Newbie
 
Registered: Jun 2015
Posts: 2

Original Poster
Rep: Reputation: Disabled
Thank you for reply smallpond!

Could you please to turn me in the right direction? Where I need to go, to filter all read/write request?
May be useful links, examples or specific source files?

PS: I do not need a continuous data, just every atomic portion.

With best regards,
Vasily
 
  


Reply



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
problem with the block device shivanag Linux - Newbie 1 08-03-2012 09:42 AM
problem with ending requests asynchronously in my block device driver cable_plug2000 Programming 0 12-15-2007 05:12 PM
Grub problem : not found or not a block device bennethos Debian 1 01-04-2005 03:54 PM
mount-problem usb harddisk: not a valid block device micha Mandriva 2 11-21-2004 10:29 AM
Problem with USB Key and creating the /dev/sda1 block device Ben2210 Slackware 5 08-04-2004 02:42 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 08:02 PM.

Main Menu
Advertisement
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
Open Source Consulting | Domain Registration