LinuxQuestions.org
LinuxAnswers - the LQ Linux tutorial section.
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 08-31-2011, 12:22 PM   #1
Agarwal6
LQ Newbie
 
Registered: Aug 2011
Posts: 3

Rep: Reputation: Disabled
Ultra slow write speed with custom linux "stacking" block device driver


Hi,

I'm developing a simple "stacking" linux block device driver. In it's simplest form, this driver will only pass all requests to the "target" device by changing the bi_bdev on the bio.

The driver uses the "make_request" to process incoming requests as opposed with having a standard request queue set up.

The problem is that write performance using this setup makes it unusable; performance is about 10% of the target device. Read performance seem mostly unaffected.

In concept, this is pretty much the same as the MD or DM drivers in linux, but with a "noop" personality; all requests are simply passed to one single target device, always. Of course MD/DM don't suffer from the write performance problem I'm describing, so I want to find out what I'm doing wrong.

Here's the simplest driver I could write that exposes the problem:

https://github.com/wegel/passthrough

It's been tested against 2.6.38. To try it, make sure you define TARGET_NAME to an existing device. Once loaded, /dev/passthrough will appear. To quickly test write speed, I do:

WARNING: the following will effectively write zeroes to your target device, destroying it's MBR and partitions. Don't use a target device on which you have actual data!!
Code:
sudo dd if=/dev/zero of=/dev/passthrough bs=1024 count=10000
Please let me know if you have any idea what I'm doing wrong, or if you have a suggestion on where to post my question to get a better chance to have it answered. Thanks!

Last edited by Agarwal6; 08-31-2011 at 01:57 PM.
 
Old 09-01-2011, 12:35 AM   #2
kbp
Senior Member
 
Registered: Aug 2009
Posts: 3,758

Rep: Reputation: 643Reputation: 643Reputation: 643Reputation: 643Reputation: 643Reputation: 643
Not a direct answer, but if it was me I'd be looking at the source for similar drivers to see how they were built. Theres no point hitting the same problems that have been solved years ago.
 
Old 09-01-2011, 11:21 AM   #3
Agarwal6
LQ Newbie
 
Registered: Aug 2011
Posts: 3

Original Poster
Rep: Reputation: Disabled
Indeed; that's pretty much what I did and am still doing, but I just can't seem to find the actual difference that'll fix the problem. That's why I'm asking for help.
 
Old 09-01-2011, 12:33 PM   #4
Proud
Senior Member
 
Registered: Dec 2002
Location: England
Distribution: Used to use Mandrake/Mandriva
Posts: 2,794

Rep: Reputation: 116Reputation: 116
Just playing the game of hate-the-magic-numbers-in-code, have you checked the values on lines 102-103
Code:
dev->gd->queue->limits.logical_block_size = 512;
dev->gd->queue->limits.physical_block_size = 512;
are best?

Also QUEUE_FLAG_NONROT indicates no seek costs, but if you're passing through to a device that has them, is this right?
And I think you OR in REQ_FUA which IDK if you should http://kernel.org/doc/Documentation/...he_control.txt
https://lkml.org/lkml/2011/5/22/46 relevant?

Last edited by Proud; 09-01-2011 at 12:42 PM.
 
Old 09-02-2011, 12:06 PM   #5
Agarwal6
LQ Newbie
 
Registered: Aug 2011
Posts: 3

Original Poster
Rep: Reputation: Disabled
@Proud: yep, I tried pretty much everything I saw in other block device drivers. No change.

Also, commenting out the block from 98-104 results in no change whatsoever, so I doubt the culprit is in there.

I'm more leaning toward a fundamental flaw somewhere in my design, maybe cache or scheduler related (?).

I found out that using the target disk's own make_request_fn seems to work, eg:

Code:
static int passthrough_make_request(struct request_queue *q, struct bio *bio)
{
	struct request_queue *target_q;
	bio->bi_bdev = passthrough->target_dev;
	target_q = bdev_get_queue(bio->bi_bdev);
	target_q->make_request_fn(target_q, bio);
	return 0;
}
But to apply this solution to my real driver, I need to understand *why* this seems to work. Any idea?
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

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
linux driver "Beyond-end write (0 4096)" archanac07 Linux - Kernel 1 01-23-2010 05:46 PM
What is it that makes Ultra X Linux so "Ultra Fast" and "Ultra Reliable?" foodown Ultra X 1 07-10-2009 06:04 PM
problem with installing linux gentoo with a "root block device" AKAKAK Linux - Distributions 15 10-23-2007 05:15 PM
"block device /dev/sda2 is write-protected, mounting read-only" - fstab problem blanks77 Linux - Hardware 1 04-28-2006 06:09 PM


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

Main Menu
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
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration