From 2cb2e147a6d20bffd1d6b7a79be7301560f751c3 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 17 Jan 2006 09:04:32 +0100 Subject: [PATCH 1/8] [BLOCK] ll_rw_blk: make max_sectors and max_hw_sectors unsigned ints IDE lba48 can support full 64k request size, which overflows the max_hw_sectors variable. Signed-off-by: Jens Axboe --- block/ll_rw_blk.c | 2 +- include/linux/blkdev.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 8e27d0ab0d7c..5c62507a510d 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -662,7 +662,7 @@ EXPORT_SYMBOL(blk_queue_bounce_limit); * Enables a low level driver to set an upper limit on the size of * received requests. **/ -void blk_queue_max_sectors(request_queue_t *q, unsigned short max_sectors) +void blk_queue_max_sectors(request_queue_t *q, unsigned int max_sectors) { if ((max_sectors << 9) < PAGE_CACHE_SIZE) { max_sectors = 1 << (PAGE_CACHE_SHIFT - 9); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 02a585faa62c..860e7a485a5f 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -392,8 +392,8 @@ struct request_queue unsigned int nr_congestion_off; unsigned int nr_batching; - unsigned short max_sectors; - unsigned short max_hw_sectors; + unsigned int max_sectors; + unsigned int max_hw_sectors; unsigned short max_phys_segments; unsigned short max_hw_segments; unsigned short hardsect_size; @@ -697,7 +697,7 @@ extern request_queue_t *blk_init_queue(request_fn_proc *, spinlock_t *); extern void blk_cleanup_queue(request_queue_t *); extern void blk_queue_make_request(request_queue_t *, make_request_fn *); extern void blk_queue_bounce_limit(request_queue_t *, u64); -extern void blk_queue_max_sectors(request_queue_t *, unsigned short); +extern void blk_queue_max_sectors(request_queue_t *, unsigned int); extern void blk_queue_max_phys_segments(request_queue_t *, unsigned short); extern void blk_queue_max_hw_segments(request_queue_t *, unsigned short); extern void blk_queue_max_segment_size(request_queue_t *, unsigned int); From 53e86061b5bd4aece9bbb6b00b30720200596ecb Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 17 Jan 2006 11:09:27 +0100 Subject: [PATCH 2/8] [BLOCK] ll_rw_blk: use preempt-disabling disk_stat_add() in completion It can legally be called with interrupts/preemption enabled. Signed-off-by: Jens Axboe --- block/ll_rw_blk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 5c62507a510d..6bc41564c70e 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -3153,7 +3153,7 @@ static int __end_that_request_first(struct request *req, int uptodate, if (blk_fs_request(req) && req->rq_disk) { const int rw = rq_data_dir(req); - __disk_stat_add(req->rq_disk, sectors[rw], nr_bytes >> 9); + disk_stat_add(req->rq_disk, sectors[rw], nr_bytes >> 9); } total_bytes = bio_nbytes = 0; From 5f00397644e01adfbebafb5d0ebc01eba522709d Mon Sep 17 00:00:00 2001 From: Nate Diller Date: Tue, 24 Jan 2006 10:07:58 +0100 Subject: [PATCH 3/8] [BLOCK] elevator: default choice selection My previous default iosched patch did a poor job dealing with the 'elevator=' boot-time option. The old behavior falls back to the compiled-in default if the requested one is not registered at boot time. This patch dynamically evaluates which default to use, and emits a suitable error message when the requested scheduler is not available. It also does the 'as' -> 'anticipatory' conversion before elevator registration, which along with a modified registration function, allows it to correctly indicate which default scheduler is in use. Tested for a range of boot options on 2.6.16-rc1-mm2. Signed-off-by: Nate Diller Signed-off-by: Jens Axboe --- block/elevator.c | 45 ++++++++++++++------------------------------- 1 file changed, 14 insertions(+), 31 deletions(-) diff --git a/block/elevator.c b/block/elevator.c index c9f424d5399c..dbbea73a8b10 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -139,35 +139,16 @@ static int elevator_attach(request_queue_t *q, struct elevator_type *e, static char chosen_elevator[16]; -static void elevator_setup_default(void) +static int __init elevator_setup(char *str) { - struct elevator_type *e; - - /* - * If default has not been set, use the compiled-in selection. - */ - if (!chosen_elevator[0]) - strcpy(chosen_elevator, CONFIG_DEFAULT_IOSCHED); - /* * Be backwards-compatible with previous kernels, so users * won't get the wrong elevator. */ - if (!strcmp(chosen_elevator, "as")) + if (!strcmp(str, "as")) strcpy(chosen_elevator, "anticipatory"); - - /* - * If the given scheduler is not available, fall back to the default - */ - if ((e = elevator_find(chosen_elevator))) - elevator_put(e); else - strcpy(chosen_elevator, CONFIG_DEFAULT_IOSCHED); -} - -static int __init elevator_setup(char *str) -{ - strncpy(chosen_elevator, str, sizeof(chosen_elevator) - 1); + strncpy(chosen_elevator, str, sizeof(chosen_elevator) - 1); return 0; } @@ -184,15 +165,15 @@ int elevator_init(request_queue_t *q, char *name) q->end_sector = 0; q->boundary_rq = NULL; - elevator_setup_default(); - - if (!name) - name = chosen_elevator; - - e = elevator_get(name); - if (!e) + if (name && !(e = elevator_get(name))) return -EINVAL; + if (!e && !(e = elevator_get(chosen_elevator))) { + e = elevator_get(CONFIG_DEFAULT_IOSCHED); + if (*chosen_elevator) + printk("I/O scheduler %s not found\n", chosen_elevator); + } + eq = kmalloc(sizeof(struct elevator_queue), GFP_KERNEL); if (!eq) { elevator_put(e); @@ -669,8 +650,10 @@ int elv_register(struct elevator_type *e) spin_unlock_irq(&elv_list_lock); printk(KERN_INFO "io scheduler %s registered", e->elevator_name); - if (!strcmp(e->elevator_name, chosen_elevator)) - printk(" (default)"); + if (!strcmp(e->elevator_name, chosen_elevator) || + (!*chosen_elevator && + !strcmp(e->elevator_name, CONFIG_DEFAULT_IOSCHED))) + printk(" (default)"); printk("\n"); return 0; } From 248d5ca5ed5feb7f1a68d213c0ff89c604a97179 Mon Sep 17 00:00:00 2001 From: Nate Diller Date: Tue, 24 Jan 2006 10:09:14 +0100 Subject: [PATCH 4/8] [BLOCK] elevator: allow default scheduler to potentially be modular Jens has decided that allowing the default scheduler to be a module is a bug, and should not be allowed under kconfig. However, I find that scenario useful for debugging, and wish for the kernel to be able to handle this situation without OOPSing, if I enable such an option in the .config directly. This patch dynamically checks for the presence of the compiled-in default, and falls back to no-op, emitting a suitable error message, when the default is not available Tested for a range of boot options on 2.6.16-rc1-mm2. Signed-off-by: Nate Diller Signed-off-by: Jens Axboe --- block/elevator.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/block/elevator.c b/block/elevator.c index dbbea73a8b10..96a61e029ce5 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -168,10 +168,12 @@ int elevator_init(request_queue_t *q, char *name) if (name && !(e = elevator_get(name))) return -EINVAL; - if (!e && !(e = elevator_get(chosen_elevator))) { - e = elevator_get(CONFIG_DEFAULT_IOSCHED); - if (*chosen_elevator) - printk("I/O scheduler %s not found\n", chosen_elevator); + if (!e && *chosen_elevator && !(e = elevator_get(chosen_elevator))) + printk("I/O scheduler %s not found\n", chosen_elevator); + + if (!e && !(e = elevator_get(CONFIG_DEFAULT_IOSCHED))) { + printk("Default I/O scheduler not found, using no-op\n"); + e = elevator_get("noop"); } eq = kmalloc(sizeof(struct elevator_queue), GFP_KERNEL); From 60481b12b8816d431308c3d974e341ab8c8c0bcf Mon Sep 17 00:00:00 2001 From: Tetsuo Takata Date: Tue, 24 Jan 2006 10:34:36 +0100 Subject: [PATCH 5/8] [BLOCK] ll_rw_blk: fix setting of ->ordered on init This makes XFS barrier mounts succeed on my SCSI system. Signed-off-by: Tetsuo Takata Signed-off-by: Jens Axboe --- block/ll_rw_blk.c | 1 + 1 file changed, 1 insertion(+) diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 6bc41564c70e..e00ab71b5e0c 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -332,6 +332,7 @@ int blk_queue_ordered(request_queue_t *q, unsigned ordered, return -EINVAL; } + q->ordered = ordered; q->next_ordered = ordered; q->prepare_flush_fn = prepare_flush_fn; From dfcd77d16b5745fbfea7d5636f15fc80cc05fef8 Mon Sep 17 00:00:00 2001 From: Tetsuo Takata Date: Wed, 25 Jan 2006 11:12:40 +0100 Subject: [PATCH 6/8] [SCSI] Remove host template ordered_flush variable After the recent overhaul of the block layer the variable "ordered_flush" is no longer used. Signed-off-by: Tetsuo Takata Signed-off-by: Jens Axboe --- include/scsi/scsi_host.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 467274a764d1..827992949c4b 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -554,7 +554,6 @@ struct Scsi_Host { /* * ordered write support */ - unsigned ordered_flush:1; unsigned ordered_tag:1; /* From 48bdc8ec4aa2ca04e339bf5c3a47677d8dd00bb6 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 30 Jan 2006 16:09:35 +0100 Subject: [PATCH 7/8] [LIBATA] Blacklist certain Maxtor firmware revisions for FUA support It looks like they are either discarding or corrupting data when the FUA command is used, bad. Signed-off-by: Jens Axboe --- drivers/scsi/libata-scsi.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index cfbceb504718..07b1e7cc61df 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -1700,6 +1700,31 @@ static unsigned int ata_msense_rw_recovery(u8 **ptr_io, const u8 *last) return sizeof(def_rw_recovery_mpage); } +/* + * We can turn this into a real blacklist if it's needed, for now just + * blacklist any Maxtor BANC1G10 revision firmware + */ +static int ata_dev_supports_fua(u16 *id) +{ + unsigned char model[41], fw[9]; + + if (!ata_id_has_fua(id)) + return 0; + + model[40] = '\0'; + fw[8] = '\0'; + + ata_dev_id_string(id, model, ATA_ID_PROD_OFS, sizeof(model) - 1); + ata_dev_id_string(id, fw, ATA_ID_FW_REV_OFS, sizeof(fw) - 1); + + if (strncmp(model, "Maxtor", 6)) + return 1; + if (strncmp(fw, "BANC1G10", 8)) + return 1; + + return 0; /* blacklisted */ +} + /** * ata_scsiop_mode_sense - Simulate MODE SENSE 6, 10 commands * @args: device IDENTIFY data / SCSI command of interest. @@ -1797,7 +1822,7 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf, return 0; dpofua = 0; - if (ata_id_has_fua(args->id) && dev->flags & ATA_DFLAG_LBA48 && + if (ata_dev_supports_fua(args->id) && dev->flags & ATA_DFLAG_LBA48 && (!(dev->flags & ATA_DFLAG_PIO) || dev->multi_count)) dpofua = 1 << 4; From fddfdeafa8396f85c666bfc5e1e920eb535514cf Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 31 Jan 2006 15:24:34 +0100 Subject: [PATCH 8/8] [BLOCK] A few kerneldoc fixups Signed-off-by: Jens Axboe --- block/ll_rw_blk.c | 2 ++ fs/bio.c | 1 + 2 files changed, 3 insertions(+) diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index e00ab71b5e0c..d38b4afa37ef 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -304,6 +304,7 @@ static inline void rq_init(request_queue_t *q, struct request *rq) * blk_queue_ordered - does this queue support ordered writes * @q: the request queue * @ordered: one of QUEUE_ORDERED_* + * @prepare_flush_fn: rq setup helper for cache flush ordered writes * * Description: * For journalled file systems, doing ordered writes on a commit @@ -2633,6 +2634,7 @@ EXPORT_SYMBOL(blk_put_request); /** * blk_end_sync_rq - executes a completion event on a request * @rq: request to complete + * @error: end io status of the request */ void blk_end_sync_rq(struct request *rq, int error) { diff --git a/fs/bio.c b/fs/bio.c index bbc442b8c867..1f3bb501c262 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -411,6 +411,7 @@ static int __bio_add_page(request_queue_t *q, struct bio *bio, struct page /** * bio_add_pc_page - attempt to add page to bio + * @q: the target queue * @bio: destination bio * @page: page to add * @len: vec entry length