ide write barriers
Subsystems (2)
PATCH 1/1 ide write barriers
Hi,
The attached patch implements write barrier operations in the block layer and for IDE, specifically. The goal is to make the use of write back cache enabled ide drives safe with journalled file systems.
Patch is against 2.4.21-pre4-bk as of today, and includes a small patch to enable it on ext3. Chris has a patch for reiserfs as well.
===== drivers/block/elevator.c 1.7 vs edited =====
drivers/block/elevator.c +6 -0
@@ -156,6 +156,12 @@while ((entry = entry->prev) != head) {struct request *__rq =blkdev_entry_to_request (entry); +/* +* we can neither merge nor insert before/with a flush +*/ +if (__rq->cmd_flags &RQ_WRITE_ORDERED ) +break ; +if (__rq->cmd != rw)continue ;if (__rq->rq_dev != bh->b_rdev)
===== drivers/block/ll_rw_blk.c 1.42 vs edited =====
drivers/block/ll_rw_blk.c +49 -2
89 lines not on this page · raw message
===== drivers/ide/ide-disk.c 1.12 vs edited =====
drivers/ide/ide-disk.c +1 -26
@@ -766,32 +766,7 @@static int idedisk_end_request (ide_drive_t *drive,int uptodate) { -struct request *rq; -unsigned long flags; -int ret =1 ; - -spin_lock_irqsave (&io_request_lock, flags); - rq =HWGROUP (drive)->rq; - -/* -* decide whether to reenable DMA -- 3 is a random magic for now, -* if we DMA timeout more than 3 times, just stay in PIO -*/ -if (drive->state ==DMA_PIO_RETRY && drive->retry_pio <=3 ) { - drive->state =0 ; -HWGROUP (drive)->hwif->ide_dma_on (drive); - } - -if (!end_that_request_first (rq, uptodate, drive->name)) { -add_blkdev_randomness (MAJOR (rq->rq_dev)); -blkdev_dequeue_request (rq); -HWGROUP (drive)->rq =NULL ; -end_that_request_last (rq); - ret =0 ; - } - -spin_unlock_irqrestore (&io_request_lock, flags); -return ret; +return ide_end_request (drive, uptodate); }static u8 idedisk_dump_status (ide_drive_t *drive,const char *msg,u8 stat)
===== drivers/ide/ide-io.c 1.2 vs edited =====
drivers/ide/ide-io.c +99 -5
150 lines not on this page · raw message
===== drivers/ide/ide-probe.c 1.14 vs edited =====
drivers/ide/ide-probe.c +2 -5
@@ -784,11 +784,8 @@ q->queuedata =HWGROUP (drive);blk_init_queue (q, do_ide_request); -if (drive->media == ide_disk) { -#ifdef CONFIG_BLK_DEV_ELEVATOR_NOOP -elevator_init (&q->elevator,ELEVATOR_NOOP ); -#endif - } +if (drive->media == ide_disk) +blk_queue_ordered (&drive->queue,QUEUE_ORDERED_FLUSH ); }#undef __IRQ_HELL_SPIN
===== fs/jbd/commit.c 1.5 vs edited =====
fs/jbd/commit.c +8 -0
@@ -598,7 +598,15 @@struct buffer_head *bh =jh2bh (descriptor);clear_bit (BH_Dirty, &bh->b_state); bh->b_end_io = journal_end_buffer_io_sync; + +/* if we're on an ide device, setting BH_Ordered_Flush +will force a write cache flush before and after the +commit block. Otherwise, it'll do nothing. */ + +set_bit (BH_Ordered_Flush, &bh->b_state);submit_bh (WRITE , bh); +clear_bit (BH_Ordered_Flush, &bh->b_state); +wait_on_buffer (bh);put_bh (bh);/* One for getblk() */ journal_unlock_journal_head (descriptor);
===== include/linux/blkdev.h 1.23 vs edited =====
include/linux/blkdev.h +13 -0
@@ -32,6 +32,7 @@kdev_t rq_dev;int cmd;/* READ or WRITE */ +unsigned long cmd_flags;int errors;unsigned long start_time;unsigned long sector;
@@ -48,6 +49,10 @@request_queue_t *q; }; +#define RQ_WRITE_ORDERED 1/* ordered write */ +#define RQ_WRITE_PREFLUSH 2/* pre-barrier flush */ +#define RQ_WRITE_POSTFLUSH 4/* post-barrier flush */ +#include <linux/elevator.h> typedef int (merge_request_fn) (request_queue_t *q,
@@ -127,6 +132,10 @@char head_active;unsigned long bounce_pfn; +/* +* ordered write support +*/ +char ordered;/* * Is meant to protect the queue in the future instead of
@@ -156,6 +165,9 @@ } } +#define QUEUE_ORDERED_NONE 0/* no support */ +#define QUEUE_ORDERED_TAG 1/* supported by tags (fast) */ +#define QUEUE_ORDERED_FLUSH 2/* supported by cache flush (ugh!) */ extern unsigned long blk_max_low_pfn, blk_max_pfn;#define BLK_BOUNCE_HIGH (blk_max_low_pfn << PAGE_SHIFT)
@@ -225,6 +237,7 @@extern void blk_init_queue (request_queue_t *,request_fn_proc *);extern void blk_cleanup_queue (request_queue_t *);extern void blk_queue_headactive (request_queue_t *,int ); +extern void blk_queue_ordered (request_queue_t *,int );extern void blk_queue_make_request (request_queue_t *,make_request_fn *);extern void generic_unplug_device (void *);extern inline int blk_seg_merge_ok (struct buffer_head *,struct buffer_head *);
===== include/linux/fs.h 1.74 vs edited =====
include/linux/fs.h +8 -1
@@ -221,6 +221,10 @@ BH_Launder,/* 1 if we can throttle on this buffer */ BH_Attached,/* 1 if b_inode_buffers is linked into a list */ BH_JBD ,/* 1 if it has an attached journal_head */ + BH_Ordered_Tag,/* 1 if this buffer is a ordered write barrier */ + BH_Ordered_Flush,/* 1 if this buffer is a flush write barrier */ + BH_Ordered_Hard,/* 1 if barrier required by the caller */ +BH_IO_OPNOTSUPP ,/* 1 if block layer rejected a barrier write */ BH_PrivateStart,/* not a state bit, but the first bit available * for private allocation by other entities
@@ -283,7 +287,10 @@#define buffer_new (bh) __buffer_state(bh,New)#define buffer_async (bh) __buffer_state(bh,Async)#define buffer_launder (bh) __buffer_state(bh,Launder) - +#define buffer_ordered_tag (bh) __buffer_state(bh,Ordered_Tag) +#define buffer_ordered_hard (bh) __buffer_state(bh,Ordered_Hard) +#define buffer_ordered_flush (bh) __buffer_state(bh,Ordered_Flush) +#define bh_offset (bh) ((unsigned long)(bh)->b_data & ~PAGE_MASK)extern void set_bh_page (struct buffer_head *bh,struct page *page,unsigned long offset);
===== include/linux/ide.h 1.9 vs edited =====
include/linux/ide.h +3 -0
@@ -743,6 +743,7 @@ unsigned remap_0_to_1 : 2; /* 0=remap if ezdrive, 1=remap, 2=noremap */ unsigned ata_flash : 1; /* 1=present, 0=default */ unsigned dead : 1; /* 1=dead, no new attachments */ + unsigned doing_barrier : 1; /* state, 1=currently doing flush */unsigned addressing;/* : 3; * 0=28-bit * 1=48-bit
@@ -788,6 +789,8 @@int forced_lun;/* if hdxlun was given at boot */ int lun;/* logical unit */ int crc_count;/* crc counter to reduce drive speed */ + +char special_buf[4 ];/* IDE_DRIVE_CMD, free use */ } ide_drive_t; typedef struct ide_pio_ops_s {
Signature · 1 line
Jens Axboe
On Wednesday 05 February 2003 16:18, Jens Axboe wrote:
Hi Jens,
Quoted 5 lines
The attached patch implements write barrier operations in the block layer and for IDE, specifically. The goal is to make the use of write back cache enabled ide drives safe with journalled file systems. Patch is against 2.4.21-pre4-bk as of today, and includes a small patch to enable it on ext3. Chris has a patch for reiserfs as well.
Could you also please cook up one for 2.4.20? :) Thank you.
ciao, Marc
Quoted 10 lines · Marc-Christian Petersen
On Wednesday 05 February 2003 16:18, Jens Axboe wrote:
Hi Jens,
Quoted 5 lines
The attached patch implements write barrier operations in the block layer and for IDE, specifically. The goal is to make the use of write back cache enabled ide drives safe with journalled file systems. Patch is against 2.4.21-pre4-bk as of today, and includes a small patch to enable it on ext3. Chris has a patch for reiserfs as well.
Could you also please cook up one for 2.4.20? :) Thank you.
Sure, I had that one already. BTW, I discovered that the default io scheduler forgets to honor the cmd_flags, it's supposed to break like the noop does (see very first hunk in very first file). Must have removed that by mistake some time ago... This applies both to the 2.4.21-pre4 patch posted and this one.
drivers/block/elevator.c renamed from opt/kernel/linux-2.4.20/drivers/block/elevator.c +6 -0
@@ -156,6 +156,12 @@while ((entry = entry->prev) != head) {struct request *__rq =blkdev_entry_to_request (entry); +/* +* we can neither merge nor insert before/with a flush +*/ +if (__rq->cmd_flags &RQ_WRITE_ORDERED ) +break ; +if (__rq->cmd != rw)continue ;if (__rq->rq_dev != bh->b_rdev)
drivers/block/ll_rw_blk.c renamed from opt/kernel/linux-2.4.20/drivers/block/ll_rw_blk.c +50 -3
97 lines not on this page · raw message
drivers/ide/ide.c renamed from opt/kernel/linux-2.4.20/drivers/ide/ide.c +112 -4
169 lines not on this page · raw message
fs/jbd/commit.c renamed from opt/kernel/linux-2.4.20/fs/jbd/commit.c +8 -0
@@ -598,7 +598,15 @@struct buffer_head *bh =jh2bh (descriptor);clear_bit (BH_Dirty, &bh->b_state); bh->b_end_io = journal_end_buffer_io_sync; + +/* if we're on an ide device, setting BH_Ordered_Flush +will force a write cache flush before and after the +commit block. Otherwise, it'll do nothing. */ + +set_bit (BH_Ordered_Flush, &bh->b_state);submit_bh (WRITE , bh); +clear_bit (BH_Ordered_Flush, &bh->b_state); +wait_on_buffer (bh);put_bh (bh);/* One for getblk() */ journal_unlock_journal_head (descriptor);
include/linux/blkdev.h renamed from opt/kernel/linux-2.4.20/include/linux/blkdev.h +13 -0
@@ -32,6 +32,7 @@kdev_t rq_dev;int cmd;/* READ or WRITE */ +unsigned long cmd_flags;int errors;unsigned long start_time;unsigned long sector;
@@ -48,6 +49,10 @@request_queue_t *q; }; +#define RQ_WRITE_ORDERED 1/* ordered write */ +#define RQ_WRITE_PREFLUSH 2/* pre-barrier flush */ +#define RQ_WRITE_POSTFLUSH 4/* post-barrier flush */ +#include <linux/elevator.h> typedef int (merge_request_fn) (request_queue_t *q,
@@ -127,6 +132,10 @@char head_active;unsigned long bounce_pfn; +/* +* ordered write support +*/ +char ordered;/* * Is meant to protect the queue in the future instead of
@@ -140,6 +149,9 @@wait_queue_head_t wait_for_requests[2 ]; }; +#define QUEUE_ORDERED_NONE 0/* no support */ +#define QUEUE_ORDERED_TAG 1/* supported by tags (fast) */ +#define QUEUE_ORDERED_FLUSH 2/* supported by cache flush (ugh!) */ extern unsigned long blk_max_low_pfn, blk_max_pfn;#define BLK_BOUNCE_HIGH (blk_max_low_pfn << PAGE_SHIFT)
@@ -209,6 +221,7 @@extern void blk_init_queue (request_queue_t *,request_fn_proc *);extern void blk_cleanup_queue (request_queue_t *);extern void blk_queue_headactive (request_queue_t *,int ); +extern void blk_queue_ordered (request_queue_t *,int );extern void blk_queue_make_request (request_queue_t *,make_request_fn *);extern void generic_unplug_device (void *);extern inline int blk_seg_merge_ok (struct buffer_head *,struct buffer_head *);
include/linux/elevator.h renamed from opt/kernel/linux-2.4.20/include/linux/elevator.h +2 -2
@@ -93,8 +93,8 @@#define ELEVATOR_LINUS \ ((elevator_t) { \ - 2048,/* read passovers */ \ -8192 ,/* write passovers */ \ + 256,/* read passovers */ \ +1024 ,/* write passovers */ \ \ elevator_linus_merge,/* elevator_merge_fn */ \ elevator_linus_merge_req, /* elevator_merge_req_fn */ \
include/linux/fs.h renamed from opt/kernel/linux-2.4.20/include/linux/fs.h +8 -1
@@ -220,6 +220,10 @@ BH_Wait_IO,/* 1 if we should write out this buffer */ BH_Launder,/* 1 if we can throttle on this buffer */ BH_JBD ,/* 1 if it has an attached journal_head */ + BH_Ordered_Tag,/* 1 if this buffer is a ordered write barrier */ + BH_Ordered_Flush,/* 1 if this buffer is a flush write barrier */ + BH_Ordered_Hard,/* 1 if barrier required by the caller */ +BH_IO_OPNOTSUPP ,/* 1 if block layer rejected a barrier write */ BH_PrivateStart,/* not a state bit, but the first bit available * for private allocation by other entities
@@ -283,7 +287,10 @@#define buffer_new (bh) __buffer_state(bh,New)#define buffer_async (bh) __buffer_state(bh,Async)#define buffer_launder (bh) __buffer_state(bh,Launder) - +#define buffer_ordered_tag (bh) __buffer_state(bh,Ordered_Tag) +#define buffer_ordered_hard (bh) __buffer_state(bh,Ordered_Hard) +#define buffer_ordered_flush (bh) __buffer_state(bh,Ordered_Flush) +#define bh_offset (bh) ((unsigned long)(bh)->b_data & ~PAGE_MASK)extern void set_bh_page (struct buffer_head *bh,struct page *page,unsigned long offset);
include/linux/ide.h renamed from opt/kernel/linux-2.4.20/include/linux/ide.h +3 -0
@@ -381,6 +381,8 @@ unsigned autotune : 2; /* 1=autotune, 2=noautotune, 0=default */ unsigned remap_0_to_1 : 2; /* 0=remap if ezdrive, 1=remap, 2=noremap */ unsigned ata_flash : 1; /* 1=present, 0=default */ + unsigned quiet : 1; + unsigned doing_barrier : 1; /* barrier sequence in progress */unsigned addressing;/* : 2; 0=28-bit, 1=48-bit, 2=64-bit */ byte scsi;/* 0=default, 1=skip current ide-subdriver for ide-scsi emulation */ byte media;/* disk, cdrom, tape, floppy, ... */
@@ -428,6 +430,7 @@byte acoustic;/* acoustic management */ unsigned int failures;/* current failure count */ unsigned int max_failures;/* maximum allowed failure count */ +char special_buf[4 ];/* IDE_DRIVE_CMD, free use */ } ide_drive_t;/*
Signature · 1 line
Jens Axboe
On Wednesday 05 February 2003 17:33, Jens Axboe wrote:
Hi Jens,
Quoted 1 line
Sure, I had that one already. BTW, I discovered that the default io
thank you :)
Quoted 4 lines
scheduler forgets to honor the
cmd_flags, it's supposed to break like the noop does (see very first hunk in very first file). Must have removed that by mistake some time ago... This applies both to the 2.4.21-pre4 patch posted and this one.
well, I am impressed, really!
As you described in the patch:
+ * For journalled file systems, doing ordered writes on a commit + * block instead of explicitly doing wait_on_buffer (which is bad + * for performance) can be a big win. Block drivers supporting this
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
I don't have benchmarks handy yet but as far as I can _feel_, this is a _MUST_ (I repeat: a _MUST_ for 2.4.21). And I am very good in feeling slowdowns for interactivity :)
I am running it for quite some hours now with 2.4.20. Well, maybe the nr_requests = 16 and read/write passovers changes in the elevator code give us more smoothness than w/o but in my theoretical mind, this should drop throughput. I also noticed, these changes aren't in your 2.4.21 patch. Can you explain why it is in 2.4.20 patch or why it isn't in 2.4.21 patch ? :)
Thanks alot.
/ME calls out for Con to do a benchmark with the 2.4.21 patch.
ciao, Marc
Quoted 24 lines · Marc-Christian Petersen
On Wednesday 05 February 2003 17:33, Jens Axboe wrote:
Hi Jens,
Quoted 1 line
Sure, I had that one already. BTW, I discovered that the default io
thank you :)
Quoted 4 lines
scheduler forgets to honor the
cmd_flags, it's supposed to break like the noop does (see very first hunk in very first file). Must have removed that by mistake some time ago... This applies both to the 2.4.21-pre4 patch posted and this one.well, I am impressed, really!
As you described in the patch:
+ * For journalled file systems, doing ordered writes on a commit + * block instead of explicitly doing wait_on_buffer (which is bad + * for performance) can be a big win. Block drivers supporting this^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
I don't have benchmarks handy yet but as far as I can _feel_, this is a _MUST_ (I repeat: a _MUST_ for 2.4.21). And I am very good in feeling slowdowns for interactivity :)
Quoted 5 lines
I am running it for quite some hours now with 2.4.20. Well, maybe the
nr_requests= 16 and read/write passovers changes in the elevator code give us more smoothness than w/o but in my theoretical mind, this should drop throughput. I also noticed, these changes aren't in your 2.4.21 patch. Can you explain why it is in 2.4.20 patch or why it isn't in 2.4.21 patch ? :)
There are not in the 2.4.21-pre patch, because the 2.4.20 got mixed with another patch. The limiting of number of queue requests is a different patch, and it's quite likely it will provide better interactiveness for you. But it will also considerably drop throughput, depends on the work load whether that's the case or not.
I don't think ext3 will show a performance boost with the supplied patch, but the stuff for reiser that Christ did definitely will.
Signature · 1 line
Jens Axboe