2.6.1-rc2 ide barrier support
Subsystems (3)
PATCH 1/1 2.6.1-rc2 ide barrier support
Hi,
Updated to work with 2.6.1-rc2. Changes since last version:
- Don't include jbd or xfs support, just ide + block layer bits. Makes it easier to include, as no actual barriers will be generated.
- Failure case in ide should _clear_ barrier support, not reset it.
Bart, would you care to review the ide bits for sanity?
===== drivers/block/ll_rw_blk.c 1.223 vs edited =====
drivers/block/ll_rw_blk.c +32 -3
@@ -245,6 +245,28 @@EXPORT_SYMBOL (blk_queue_make_request);/** +* blk_queue_ordered - does this queue support ordered writes +* @q: the request queue +* @flag: see below +* +* Description: +* 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 +* feature should call this function and indicate so. +* +**/ +void blk_queue_ordered (request_queue_t *q,int flag) +{ +if (flag) +set_bit (QUEUE_FLAG_ORDERED , &q->queue_flags); +else +clear_bit (QUEUE_FLAG_ORDERED , &q->queue_flags); +} + +EXPORT_SYMBOL (blk_queue_ordered); + +/** * blk_queue_bounce_limit - set bounce buffer limit for queue * @q: the request queue for the device * @dma_addr: bus address limit
@@ -1831,6 +1853,8 @@if (unlikely (!q))return ; + +WARN_ON (!req->ref_count);if (unlikely (--req->ref_count))return ;
@@ -1997,7 +2021,7 @@static int __make_request (request_queue_t *q,struct bio *bio) {struct request *req, *freereq =NULL ; -int el_ret, rw, nr_sectors, cur_nr_sectors, barrier, ra; +int el_ret, rw, nr_sectors, cur_nr_sectors, barrier, ra, err;sector_t sector; sector = bio->bi_sector;
@@ -2015,7 +2039,11 @@spin_lock_prefetch (q->queue_lock); - barrier =test_bit (BIO_RW_BARRIER , &bio->bi_rw); + barrier =bio_barrier (bio); +if (barrier && !test_bit (QUEUE_FLAG_ORDERED , &q->queue_flags)) { + err = -EOPNOTSUPP ; + goto end_io; + } ra = bio->bi_rw & (1 <<BIO_RW_AHEAD );
@@ -2097,6 +2125,7 @@/* * READA bit set */ + err = -EWOULDBLOCK ;if (ra) goto end_io;
@@ -2152,7 +2181,7 @@return 0 ; end_io: -bio_endio (bio, nr_sectors <<9 , -EWOULDBLOCK ); +bio_endio (bio, nr_sectors <<9 , err);return 0 ; }
===== drivers/ide/ide-disk.c 1.62 vs edited =====
drivers/ide/ide-disk.c +6 -2
@@ -1371,6 +1371,7 @@static int write_cache (ide_drive_t *drive,int arg) {ide_task_t args; +int err;if (!(drive->id->cfs_enable_2 &0x3000 ))return 1 ;
@@ -1380,7 +1381,10 @@ SETFEATURES_EN_WCACHE :SETFEATURES_DIS_WCACHE ; args.tfRegister[IDE_COMMAND_OFFSET ] =WIN_SETFEATURES ; args.command_type =ide_cmd_type_parser (&args); - (void )ide_raw_taskfile (drive, &args,NULL ); + + err =ide_raw_taskfile (drive, &args,NULL ); +if (err) +return err; drive->wcache = arg;return 0 ;
@@ -1755,7 +1759,7 @@ drive->wcache =0 ;/* Cache enabled ? */ if (drive->id->csfo &1 ) - drive->wcache =1 ; + drive->wcache =1 ;/* Cache command set available ? */ if (drive->id->cfs_enable_1 & (1 <<5 )) drive->wcache =1 ;
===== drivers/ide/ide-io.c 1.21 vs edited =====
drivers/ide/ide-io.c +215 -23
295 lines not on this page · raw message
===== drivers/md/raid1.c 1.75 vs edited =====
drivers/md/raid1.c +2 -2
@@ -889,7 +889,7 @@ conf =mddev_to_conf (mddev); bio = r1_bio->master_bio;switch (r1_bio->cmd) { -case SPECIAL : +case WRITESYNC :sync_request_write (mddev, r1_bio);break ;case READ :
@@ -999,7 +999,7 @@ r1_bio->mddev = mddev; r1_bio->sector = sector_nr; - r1_bio->cmd =SPECIAL ; + r1_bio->cmd =WRITESYNC ; r1_bio->read_disk = disk; bio = r1_bio->master_bio;
===== fs/buffer.c 1.216 vs edited =====
fs/buffer.c +3 -0
@@ -2665,6 +2665,9 @@if (rw ==READ &&buffer_dirty (bh))buffer_error (); +if (buffer_ordered (bh) && (rw ==WRITE )) + rw =WRITESYNC ; +/* Only clear out a write error when rewriting */ if (test_set_buffer_req (bh) && rw ==WRITE )clear_buffer_write_io_error (bh);
===== include/linux/blkdev.h 1.130 vs edited =====
include/linux/blkdev.h +10 -0
@@ -195,6 +195,8 @@ __REQ_PM_SUSPEND,/* suspend request */ __REQ_PM_RESUME,/* resume request */ __REQ_PM_SHUTDOWN,/* shutdown request */ + __REQ_BAR_PREFLUSH,/* barrier pre-flush done */ + __REQ_BAR_POSTFLUSH,/* barrier post-flush */ __REQ_NR_BITS, /* stops here */ };
@@ -220,6 +222,8 @@#define REQ_PM_SUSPEND (1 << __REQ_PM_SUSPEND)#define REQ_PM_RESUME (1 << __REQ_PM_RESUME)#define REQ_PM_SHUTDOWN (1 << __REQ_PM_SHUTDOWN) +#define REQ_BAR_PREFLUSH (1 << __REQ_BAR_PREFLUSH) +#define REQ_BAR_POSTFLUSH (1 << __REQ_BAR_POSTFLUSH)/* * State information carried for REQ_PM_SUSPEND and REQ_PM_RESUME
@@ -369,6 +373,7 @@#define QUEUE_FLAG_READFULL 3/* write queue has been filled */ #define QUEUE_FLAG_WRITEFULL 4/* read queue has been filled */ #define QUEUE_FLAG_DEAD 5/* queue being torn down */ +#define QUEUE_FLAG_ORDERED 6/* supports ordered writes */ #define blk_queue_plugged (q) !list_empty(&(q)->plug_list)#define blk_queue_tagged (q) test_bit(QUEUE_FLAG_QUEUED, &(q)->queue_flags)
@@ -381,6 +386,10 @@#define blk_pm_request (rq) \ ((rq)->flags & (REQ_PM_SUSPEND | REQ_PM_RESUME)) +#define blk_barrier_rq (rq) ((rq)->flags & REQ_HARDBARRIER) +#define blk_barrier_preflush (rq) ((rq)->flags & REQ_BAR_PREFLUSH) +#define blk_barrier_postflush (rq) ((rq)->flags & REQ_BAR_POSTFLUSH) +#define list_entry_rq (ptr) list_entry((ptr), struct request, queuelist)#define rq_data_dir (rq) ((rq)->flags & 1)
@@ -563,6 +572,7 @@extern void blk_queue_merge_bvec (request_queue_t *,merge_bvec_fn *);extern void blk_queue_dma_alignment (request_queue_t *,int );extern struct backing_dev_info *blk_get_backing_dev_info (struct block_device *bdev); +extern void blk_queue_ordered (request_queue_t *,int );extern int blk_rq_map_sg (request_queue_t *,struct request *,struct scatterlist *);extern void blk_dump_rq_flags (struct request *,char *);
===== include/linux/buffer_head.h 1.44 vs edited =====
include/linux/buffer_head.h +3 -1
@@ -26,6 +26,7 @@ BH_Delay,/* Buffer is not yet allocated on disk */ BH_Boundary,/* Block is followed by a discontiguity */ BH_Write_EIO,/* I/O error on write */ + BH_Ordered,/* ordered write */ BH_PrivateStart,/* not a state bit, but the first bit available* for private allocation by other entities
@@ -117,7 +118,8 @@ BUFFER_FNS(Async_Write, async_write) BUFFER_FNS(Delay, delay) BUFFER_FNS(Boundary, boundary) -BUFFER_FNS(Write_EIO,write_io_error) +BUFFER_FNS(Write_EIO, write_io_error) +BUFFER_FNS(Ordered, ordered)#define bh_offset (bh) ((unsigned long)(bh)->b_data & ~PAGE_MASK)#define touch_buffer (bh) mark_page_accessed(bh->b_page)
===== include/linux/fs.h 1.276 vs edited =====
include/linux/fs.h +1 -1
@@ -81,7 +81,7 @@#define READ 0#define WRITE 1#define READA 2/* read-ahead - don't block if no resources */ -#define SPECIAL 4/* For non-blockdevice requests in request queue */ +#define WRITESYNC ((1 << BIO_RW) | (1 << BIO_RW_BARRIER))#define SEL_IN 1#define SEL_OUT 2
===== include/linux/ide.h 1.79 vs edited =====
include/linux/ide.h +3 -0
@@ -754,6 +754,8 @@u8 bios_head;/* BIOS/fdisk/LILO number of heads */ u8 bios_sect;/* BIOS/fdisk/LILO sectors per track */ u8 queue_depth;/* max queue depth */ +u8 doing_barrier;/* state, 1=currently doing flush */ +u8 last_rq_flush;/* last rq was a flush */ unsigned int bios_cyl;/* BIOS/fdisk/LILO number of cyls */ unsigned int cyl;/* "real" number of cyls */
@@ -768,6 +770,7 @@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[8 ];/* private command buffer */ struct list_head list;struct device gendev;struct semaphore gendev_rel_sem;/* to deal with device release() */
Signature · 1 line
Jens Axboe
Quoted 1 line · Jens Axboe
Bart, would you care to review the ide bits for sanity?
Yep, here is just a first sight...
Review
Quoted 1 line
(quoted diff) +1
-0+ struct request *flush_rq = &HWGROUP(drive)->wrq;
I want to remove drive->wrq in the future.
drivers/ide/ide-io.c line 90
Quoted 9 lines
drivers/ide/ide-io.c +9
-0+memset (drive->special_buf,0 ,sizeof (drive->special_buf)); + +ide_init_drive_cmd (flush_rq); + + flush_rq->flags =REQ_DRIVE_TASK ; + flush_rq->buffer = drive->special_buf; + flush_rq->special = rq; + flush_rq->buffer[0 ] =WIN_FLUSH_CACHE ; + flush_rq->nr_sectors = rq->nr_sectors;
I think you should try use REQ_DRIVE_TASKFILE,
instead of adding drive->special_buf.
drivers/ide/ide-io.c line 220
Quoted 4 lines
drivers/ide/ide-io.c +4
-0+/* +* FIXME: probably move this somewhere else, name is bad too :) +*/ +static sector_t ide_get_error_location (ide_drive_t *drive,char *args)
This is probably useful in few other places.
--bart
Quoted 8 lines · Bartlomiej Zolnierkiewicz
Quoted 1 line · Jens Axboe
Bart, would you care to review the ide bits for sanity?
Yep, here is just a first sight...
Review
Quoted 1 line
(quoted diff) +1
-0+ struct request *flush_rq = &HWGROUP(drive)->wrq;I want to remove
drive->wrqin the future.
Yes I've wanted that, too, but only because of the ugly (and often racy) multimode crap. I'm just considering wrq a 'reserve rq' to be used where you cannot reliably get a new request atomically.
I'm open to any better ideas you have for this...
Quoted 4 lines
Quoted 4 lines
drivers/ide/ide-io.c +4
-0+memset (drive->special_buf,0 ,sizeof (drive->special_buf)); + +ide_init_drive_cmd (flush_rq); +
Quoted 8 lines
drivers/ide/ide-io.c line 90
Quoted 5 lines
drivers/ide/ide-io.c +5
-0+ flush_rq->flags =REQ_DRIVE_TASK ; + flush_rq->buffer = drive->special_buf; + flush_rq->special = rq; + flush_rq->buffer[0 ] =WIN_FLUSH_CACHE ; + flush_rq->nr_sectors = rq->nr_sectors;I think you should try use
REQ_DRIVE_TASKFILE,
instead of addingdrive->special_buf.
How does that change anything? I still need a command buffer, if I use REQ_DRIVE_TASKFILE I need an even bigger one.
Quoted 6 lines
drivers/ide/ide-io.c line 220
Quoted 4 lines
drivers/ide/ide-io.c +4
-0+/* +* FIXME: probably move this somewhere else, name is bad too :) +*/ +static sector_t ide_get_error_location (ide_drive_t *drive,char *args)This is probably useful in few other places.
Yeah, as the comment states I know it's not really in the right place. Where do you want it? And any suggestions for a better name? :)
Signature · 1 line
Jens Axboe
include/linux/ide.h line 773
Quoted 2 lines
include/linux/ide.h +1
-0+char special_buf[8 ];/* private command buffer */
Why not put that in struct drive instead ? You must be a bit more careful on the lifetime, but it's less bloat, there are much less instances of struct drive than struct request :)
Ben.
Quoted 6 lines · Benjamin Herrenschmidt
include/linux/ide.h line 773
Quoted 2 lines
include/linux/ide.h +1
-0+char special_buf[8 ];/* private command buffer */ Why not put that in struct drive instead ? You must be a bit more careful on the lifetime, but it's less bloat, there are much less instances of struct drive than struct request :)
Hmm? It _is_ in struct drive :-). It could be put in hwgroup actually, but I felt it was cleaner in drive (and easier to manage).
Signature · 1 line
Jens Axboe
Quoted 3 lines
Hmm? It _is_ in struct drive :-). It could be put in hwgroup actually, but I felt it was cleaner in drive (and easier to manage).
Oops :) I misread the patch, or was on crack or something... sorry :)
Ben.