LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Ultra slow write speed with custom linux "stacking" block device driver (https://www.linuxquestions.org/questions/programming-9/ultra-slow-write-speed-with-custom-linux-stacking-block-device-driver-900434/)

Agarwal6 08-31-2011 12:22 PM

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!

kbp 09-01-2011 12:35 AM

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.

Agarwal6 09-01-2011 11:21 AM

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.

Proud 09-01-2011 12:33 PM

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?

Agarwal6 09-02-2011 12:06 PM

@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?


All times are GMT -5. The time now is 03:11 PM.