From 9dfa52831e96194b8649613e3131baa2c109f7dc Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 16 Aug 2007 13:27:52 +0200 Subject: [PATCH 01/37] Merge blk_recount_segments into blk_recalc_rq_segments blk_recalc_rq_segments calls blk_recount_segments on each bio, then does some extra calculations to handle segments that overlap two bios. If we merge the code from blk_recount_segments into blk_recalc_rq_segments, we can process the whole request one bio_vec at a time, and not need the messy cross-bio calculations. Then blk_recount_segments can be implemented by calling blk_recalc_rq_segments, passing it a simple on-stack request which stores just the bio. Signed-off-by: Neil Brown diff .prev/block/ll_rw_blk.c ./block/ll_rw_blk.c Signed-off-by: Jens Axboe --- block/ll_rw_blk.c | 106 ++++++++++++++++++++-------------------------- 1 file changed, 46 insertions(+), 60 deletions(-) diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index ed39313c4085..e35119a72a44 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -42,6 +42,7 @@ static void drive_stat_acct(struct request *rq, int nr_sectors, int new_io); static void init_request_from_bio(struct request *req, struct bio *bio); static int __make_request(struct request_queue *q, struct bio *bio); static struct io_context *current_io_context(gfp_t gfp_flags, int node); +static void blk_recalc_rq_segments(struct request *rq); /* * For the allocated request tables @@ -1220,16 +1221,42 @@ EXPORT_SYMBOL(blk_dump_rq_flags); void blk_recount_segments(struct request_queue *q, struct bio *bio) { - struct bio_vec *bv, *bvprv = NULL; - int i, nr_phys_segs, nr_hw_segs, seg_size, hw_seg_size, cluster; - int high, highprv = 1; + struct request rq; + struct bio *nxt = bio->bi_next; + rq.q = q; + rq.bio = rq.biotail = bio; + bio->bi_next = NULL; + blk_recalc_rq_segments(&rq); + bio->bi_next = nxt; + bio->bi_phys_segments = rq.nr_phys_segments; + bio->bi_hw_segments = rq.nr_hw_segments; + bio->bi_flags |= (1 << BIO_SEG_VALID); +} +EXPORT_SYMBOL(blk_recount_segments); - if (unlikely(!bio->bi_io_vec)) +static void blk_recalc_rq_segments(struct request *rq) +{ + int nr_phys_segs; + int nr_hw_segs; + unsigned int phys_size; + unsigned int hw_size; + struct bio_vec *bv, *bvprv = NULL; + int seg_size; + int hw_seg_size; + int cluster; + struct bio *bio; + int i; + int high, highprv = 1; + struct request_queue *q = rq->q; + + if (!rq->bio) return; cluster = q->queue_flags & (1 << QUEUE_FLAG_CLUSTER); - hw_seg_size = seg_size = nr_phys_segs = nr_hw_segs = 0; - bio_for_each_segment(bv, bio, i) { + hw_seg_size = seg_size = 0; + phys_size = hw_size = nr_phys_segs = nr_hw_segs = 0; + rq_for_each_bio(bio, rq) + bio_for_each_segment(bv, bio, i) { /* * the trick here is making sure that a high page is never * considered part of another segment, since that might @@ -1255,12 +1282,13 @@ void blk_recount_segments(struct request_queue *q, struct bio *bio) } new_segment: if (BIOVEC_VIRT_MERGEABLE(bvprv, bv) && - !BIOVEC_VIRT_OVERSIZE(hw_seg_size + bv->bv_len)) { + !BIOVEC_VIRT_OVERSIZE(hw_seg_size + bv->bv_len)) hw_seg_size += bv->bv_len; - } else { + else { new_hw_segment: - if (hw_seg_size > bio->bi_hw_front_size) - bio->bi_hw_front_size = hw_seg_size; + if (nr_hw_segs == 1 && + hw_seg_size > rq->bio->bi_hw_front_size) + rq->bio->bi_hw_front_size = hw_seg_size; hw_seg_size = BIOVEC_VIRT_START_SIZE(bv) + bv->bv_len; nr_hw_segs++; } @@ -1270,15 +1298,15 @@ new_hw_segment: seg_size = bv->bv_len; highprv = high; } - if (hw_seg_size > bio->bi_hw_back_size) - bio->bi_hw_back_size = hw_seg_size; - if (nr_hw_segs == 1 && hw_seg_size > bio->bi_hw_front_size) - bio->bi_hw_front_size = hw_seg_size; - bio->bi_phys_segments = nr_phys_segs; - bio->bi_hw_segments = nr_hw_segs; - bio->bi_flags |= (1 << BIO_SEG_VALID); + + if (nr_hw_segs == 1 && + hw_seg_size > rq->bio->bi_hw_front_size) + rq->bio->bi_hw_front_size = hw_seg_size; + if (hw_seg_size > rq->biotail->bi_hw_back_size) + rq->biotail->bi_hw_back_size = hw_seg_size; + rq->nr_phys_segments = nr_phys_segs; + rq->nr_hw_segments = nr_hw_segs; } -EXPORT_SYMBOL(blk_recount_segments); static int blk_phys_contig_segment(struct request_queue *q, struct bio *bio, struct bio *nxt) @@ -3329,48 +3357,6 @@ void submit_bio(int rw, struct bio *bio) EXPORT_SYMBOL(submit_bio); -static void blk_recalc_rq_segments(struct request *rq) -{ - struct bio *bio, *prevbio = NULL; - int nr_phys_segs, nr_hw_segs; - unsigned int phys_size, hw_size; - struct request_queue *q = rq->q; - - if (!rq->bio) - return; - - phys_size = hw_size = nr_phys_segs = nr_hw_segs = 0; - rq_for_each_bio(bio, rq) { - /* Force bio hw/phys segs to be recalculated. */ - bio->bi_flags &= ~(1 << BIO_SEG_VALID); - - nr_phys_segs += bio_phys_segments(q, bio); - nr_hw_segs += bio_hw_segments(q, bio); - if (prevbio) { - int pseg = phys_size + prevbio->bi_size + bio->bi_size; - int hseg = hw_size + prevbio->bi_size + bio->bi_size; - - if (blk_phys_contig_segment(q, prevbio, bio) && - pseg <= q->max_segment_size) { - nr_phys_segs--; - phys_size += prevbio->bi_size + bio->bi_size; - } else - phys_size = 0; - - if (blk_hw_contig_segment(q, prevbio, bio) && - hseg <= q->max_segment_size) { - nr_hw_segs--; - hw_size += prevbio->bi_size + bio->bi_size; - } else - hw_size = 0; - } - prevbio = bio; - } - - rq->nr_phys_segments = nr_phys_segs; - rq->nr_hw_segments = nr_hw_segs; -} - static void blk_recalc_rq_sectors(struct request *rq, int nsect) { if (blk_fs_request(rq)) { From 5705f7021748a69d84d6567e68e8851dab551464 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 25 Sep 2007 12:35:59 +0200 Subject: [PATCH 02/37] Introduce rq_for_each_segment replacing rq_for_each_bio Every usage of rq_for_each_bio wraps a usage of bio_for_each_segment, so these can be combined into rq_for_each_segment. We define "struct req_iterator" to hold the 'bio' and 'index' that are needed for the double iteration. Signed-off-by: Neil Brown Various compile fixes by me... Signed-off-by: Jens Axboe --- Documentation/block/biodoc.txt | 20 ++++----- block/ll_rw_blk.c | 19 +++----- drivers/block/floppy.c | 81 ++++++++++++++++------------------ drivers/block/lguest_blk.c | 10 ++--- drivers/block/nbd.c | 22 ++++----- drivers/block/ps3disk.c | 31 ++++++------- drivers/block/xen-blkfront.c | 7 +-- drivers/ide/ide-floppy.c | 16 +++---- drivers/s390/block/dasd_diag.c | 11 ++--- drivers/s390/block/dasd_eckd.c | 15 +++---- drivers/s390/block/dasd_fba.c | 15 +++---- drivers/s390/char/tape_34xx.c | 15 +++---- drivers/s390/char/tape_3590.c | 16 +++---- include/linux/blkdev.h | 15 ++++++- 14 files changed, 131 insertions(+), 162 deletions(-) diff --git a/Documentation/block/biodoc.txt b/Documentation/block/biodoc.txt index 8af392fc6ef0..dc3f49e3e539 100644 --- a/Documentation/block/biodoc.txt +++ b/Documentation/block/biodoc.txt @@ -477,9 +477,9 @@ With this multipage bio design: the same bi_io_vec array, but with the index and size accordingly modified) - A linked list of bios is used as before for unrelated merges (*) - this avoids reallocs and makes independent completions easier to handle. -- Code that traverses the req list needs to make a distinction between - segments of a request (bio_for_each_segment) and the distinct completion - units/bios (rq_for_each_bio). +- Code that traverses the req list can find all the segments of a bio + by using rq_for_each_segment. This handles the fact that a request + has multiple bios, each of which can have multiple segments. - Drivers which can't process a large bio in one shot can use the bi_idx field to keep track of the next bio_vec entry to process. (e.g a 1MB bio_vec needs to be handled in max 128kB chunks for IDE) @@ -664,14 +664,14 @@ in lvm or md. 3.2.1 Traversing segments and completion units in a request -The macros bio_for_each_segment() and rq_for_each_bio() should be used for -traversing the bios in the request list (drivers should avoid directly -trying to do it themselves). Using these helpers should also make it easier -to cope with block changes in the future. +The macro rq_for_each_segment() should be used for traversing the bios +in the request list (drivers should avoid directly trying to do it +themselves). Using these helpers should also make it easier to cope +with block changes in the future. - rq_for_each_bio(bio, rq) - bio_for_each_segment(bio_vec, bio, i) - /* bio_vec is now current segment */ + struct req_iterator iter; + rq_for_each_segment(bio_vec, rq, iter) + /* bio_vec is now current segment */ I/O completion callbacks are per-bio rather than per-segment, so drivers that traverse bio chains on completion need to keep that in mind. Drivers diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index e35119a72a44..094c0fa5c405 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -1244,8 +1244,7 @@ static void blk_recalc_rq_segments(struct request *rq) int seg_size; int hw_seg_size; int cluster; - struct bio *bio; - int i; + struct req_iterator iter; int high, highprv = 1; struct request_queue *q = rq->q; @@ -1255,8 +1254,7 @@ static void blk_recalc_rq_segments(struct request *rq) cluster = q->queue_flags & (1 << QUEUE_FLAG_CLUSTER); hw_seg_size = seg_size = 0; phys_size = hw_size = nr_phys_segs = nr_hw_segs = 0; - rq_for_each_bio(bio, rq) - bio_for_each_segment(bv, bio, i) { + rq_for_each_segment(bv, rq, iter) { /* * the trick here is making sure that a high page is never * considered part of another segment, since that might @@ -1353,8 +1351,8 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq, struct scatterlist *sg) { struct bio_vec *bvec, *bvprv; - struct bio *bio; - int nsegs, i, cluster; + struct req_iterator iter; + int nsegs, cluster; nsegs = 0; cluster = q->queue_flags & (1 << QUEUE_FLAG_CLUSTER); @@ -1363,11 +1361,7 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq, * for each bio in rq */ bvprv = NULL; - rq_for_each_bio(bio, rq) { - /* - * for each segment in bio - */ - bio_for_each_segment(bvec, bio, i) { + rq_for_each_segment(bvec, rq, iter) { int nbytes = bvec->bv_len; if (bvprv && cluster) { @@ -1390,8 +1384,7 @@ new_segment: nsegs++; } bvprv = bvec; - } /* segments in bio */ - } /* bios in rq */ + } /* segments in rq */ return nsegs; } diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 085b7794fb3e..f0a86e201b44 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -2437,22 +2437,19 @@ static void rw_interrupt(void) /* Compute maximal contiguous buffer size. */ static int buffer_chain_size(void) { - struct bio *bio; struct bio_vec *bv; - int size, i; + int size; + struct req_iterator iter; char *base; base = bio_data(current_req->bio); size = 0; - rq_for_each_bio(bio, current_req) { - bio_for_each_segment(bv, bio, i) { - if (page_address(bv->bv_page) + bv->bv_offset != - base + size) - break; + rq_for_each_segment(bv, current_req, iter) { + if (page_address(bv->bv_page) + bv->bv_offset != base + size) + break; - size += bv->bv_len; - } + size += bv->bv_len; } return size >> 9; @@ -2479,9 +2476,9 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2) { int remaining; /* number of transferred 512-byte sectors */ struct bio_vec *bv; - struct bio *bio; char *buffer, *dma_buffer; - int size, i; + int size; + struct req_iterator iter; max_sector = transfer_size(ssize, min(max_sector, max_sector_2), @@ -2514,43 +2511,41 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2) size = current_req->current_nr_sectors << 9; - rq_for_each_bio(bio, current_req) { - bio_for_each_segment(bv, bio, i) { - if (!remaining) - break; + rq_for_each_segment(bv, current_req, iter) { + if (!remaining) + break; - size = bv->bv_len; - SUPBOUND(size, remaining); + size = bv->bv_len; + SUPBOUND(size, remaining); - buffer = page_address(bv->bv_page) + bv->bv_offset; + buffer = page_address(bv->bv_page) + bv->bv_offset; #ifdef FLOPPY_SANITY_CHECK - if (dma_buffer + size > - floppy_track_buffer + (max_buffer_sectors << 10) || - dma_buffer < floppy_track_buffer) { - DPRINT("buffer overrun in copy buffer %d\n", - (int)((floppy_track_buffer - - dma_buffer) >> 9)); - printk("fsector_t=%d buffer_min=%d\n", - fsector_t, buffer_min); - printk("current_count_sectors=%ld\n", - current_count_sectors); - if (CT(COMMAND) == FD_READ) - printk("read\n"); - if (CT(COMMAND) == FD_WRITE) - printk("write\n"); - break; - } - if (((unsigned long)buffer) % 512) - DPRINT("%p buffer not aligned\n", buffer); -#endif + if (dma_buffer + size > + floppy_track_buffer + (max_buffer_sectors << 10) || + dma_buffer < floppy_track_buffer) { + DPRINT("buffer overrun in copy buffer %d\n", + (int)((floppy_track_buffer - + dma_buffer) >> 9)); + printk("fsector_t=%d buffer_min=%d\n", + fsector_t, buffer_min); + printk("current_count_sectors=%ld\n", + current_count_sectors); if (CT(COMMAND) == FD_READ) - memcpy(buffer, dma_buffer, size); - else - memcpy(dma_buffer, buffer, size); - - remaining -= size; - dma_buffer += size; + printk("read\n"); + if (CT(COMMAND) == FD_WRITE) + printk("write\n"); + break; } + if (((unsigned long)buffer) % 512) + DPRINT("%p buffer not aligned\n", buffer); +#endif + if (CT(COMMAND) == FD_READ) + memcpy(buffer, dma_buffer, size); + else + memcpy(dma_buffer, buffer, size); + + remaining -= size; + dma_buffer += size; } #ifdef FLOPPY_SANITY_CHECK if (remaining) { diff --git a/drivers/block/lguest_blk.c b/drivers/block/lguest_blk.c index 160cf14431ac..1e838ae60a60 100644 --- a/drivers/block/lguest_blk.c +++ b/drivers/block/lguest_blk.c @@ -142,12 +142,11 @@ static irqreturn_t lgb_irq(int irq, void *_bd) * return the total length. */ static unsigned int req_to_dma(struct request *req, struct lguest_dma *dma) { - unsigned int i = 0, idx, len = 0; - struct bio *bio; + unsigned int i = 0, len = 0; + struct req_iterator iter; + struct bio_vec *bvec; - rq_for_each_bio(bio, req) { - struct bio_vec *bvec; - bio_for_each_segment(bvec, bio, idx) { + rq_for_each_segment(bvec, req, iter) { /* We told the block layer not to give us too many. */ BUG_ON(i == LGUEST_MAX_DMA_SECTIONS); /* If we had a zero-length segment, it would look like @@ -160,7 +159,6 @@ static unsigned int req_to_dma(struct request *req, struct lguest_dma *dma) dma->len[i] = bvec->bv_len; len += bvec->bv_len; i++; - } } /* If the array isn't full, we mark the end with a 0 length */ if (i < LGUEST_MAX_DMA_SECTIONS) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index be92c658f06e..228b2ff577aa 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -180,7 +180,7 @@ static inline int sock_send_bvec(struct socket *sock, struct bio_vec *bvec, static int nbd_send_req(struct nbd_device *lo, struct request *req) { - int result, i, flags; + int result, flags; struct nbd_request request; unsigned long size = req->nr_sectors << 9; struct socket *sock = lo->sock; @@ -205,16 +205,15 @@ static int nbd_send_req(struct nbd_device *lo, struct request *req) } if (nbd_cmd(req) == NBD_CMD_WRITE) { - struct bio *bio; + struct req_iterator iter; + struct bio_vec *bvec; /* * we are really probing at internals to determine * whether to set MSG_MORE or not... */ - rq_for_each_bio(bio, req) { - struct bio_vec *bvec; - bio_for_each_segment(bvec, bio, i) { + rq_for_each_segment(bvec, req, iter) { flags = 0; - if ((i < (bio->bi_vcnt - 1)) || bio->bi_next) + if (!rq_iter_last(req, iter)) flags = MSG_MORE; dprintk(DBG_TX, "%s: request %p: sending %d bytes data\n", lo->disk->disk_name, req, @@ -226,7 +225,6 @@ static int nbd_send_req(struct nbd_device *lo, struct request *req) result); goto error_out; } - } } } return 0; @@ -321,11 +319,10 @@ static struct request *nbd_read_stat(struct nbd_device *lo) dprintk(DBG_RX, "%s: request %p: got reply\n", lo->disk->disk_name, req); if (nbd_cmd(req) == NBD_CMD_READ) { - int i; - struct bio *bio; - rq_for_each_bio(bio, req) { - struct bio_vec *bvec; - bio_for_each_segment(bvec, bio, i) { + struct req_iterator iter; + struct bio_vec *bvec; + + rq_for_each_segment(bvec, req, iter) { result = sock_recv_bvec(sock, bvec); if (result <= 0) { printk(KERN_ERR "%s: Receive data failed (result %d)\n", @@ -336,7 +333,6 @@ static struct request *nbd_read_stat(struct nbd_device *lo) } dprintk(DBG_RX, "%s: request %p: got %d bytes data\n", lo->disk->disk_name, req, bvec->bv_len); - } } } return req; diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c index aa8b890c80d7..8953e7ce0016 100644 --- a/drivers/block/ps3disk.c +++ b/drivers/block/ps3disk.c @@ -91,30 +91,30 @@ static void ps3disk_scatter_gather(struct ps3_storage_device *dev, struct request *req, int gather) { unsigned int offset = 0; - struct bio *bio; - sector_t sector; + struct req_iterator iter; struct bio_vec *bvec; - unsigned int i = 0, j; + unsigned int i = 0; size_t size; void *buf; - rq_for_each_bio(bio, req) { - sector = bio->bi_sector; + rq_for_each_segment(bvec, req, iter) { + unsigned long flags; dev_dbg(&dev->sbd.core, "%s:%u: bio %u: %u segs %u sectors from %lu\n", - __func__, __LINE__, i, bio_segments(bio), - bio_sectors(bio), sector); - bio_for_each_segment(bvec, bio, j) { + __func__, __LINE__, i, bio_segments(iter.bio), + bio_sectors(iter.bio), + (unsigned long)iter.bio->bi_sector); + size = bvec->bv_len; - buf = __bio_kmap_atomic(bio, j, KM_IRQ0); + buf = bvec_kmap_irq(bvec, &flags); if (gather) memcpy(dev->bounce_buf+offset, buf, size); else memcpy(buf, dev->bounce_buf+offset, size); offset += size; - flush_kernel_dcache_page(bio_iovec_idx(bio, j)->bv_page); - __bio_kunmap_atomic(bio, KM_IRQ0); - } + flush_kernel_dcache_page(bvec->bv_page); + bvec_kunmap_irq(bvec, &flags); + i++; } } @@ -130,12 +130,13 @@ static int ps3disk_submit_request_sg(struct ps3_storage_device *dev, #ifdef DEBUG unsigned int n = 0; - struct bio *bio; + struct bio_vec *bv; + struct req_iterator iter; - rq_for_each_bio(bio, req) + rq_for_each_segment(bv, req, iter) n++; dev_dbg(&dev->sbd.core, - "%s:%u: %s req has %u bios for %lu sectors %lu hard sectors\n", + "%s:%u: %s req has %u bvecs for %lu sectors %lu hard sectors\n", __func__, __LINE__, op, n, req->nr_sectors, req->hard_nr_sectors); #endif diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 964e51634f2d..6af250113c2a 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -150,9 +150,8 @@ static int blkif_queue_request(struct request *req) struct blkfront_info *info = req->rq_disk->private_data; unsigned long buffer_mfn; struct blkif_request *ring_req; - struct bio *bio; + struct req_iterator iter; struct bio_vec *bvec; - int idx; unsigned long id; unsigned int fsect, lsect; int ref; @@ -186,8 +185,7 @@ static int blkif_queue_request(struct request *req) ring_req->operation = BLKIF_OP_WRITE_BARRIER; ring_req->nr_segments = 0; - rq_for_each_bio (bio, req) { - bio_for_each_segment (bvec, bio, idx) { + rq_for_each_segment(bvec, req, iter) { BUG_ON(ring_req->nr_segments == BLKIF_MAX_SEGMENTS_PER_REQUEST); buffer_mfn = pfn_to_mfn(page_to_pfn(bvec->bv_page)); @@ -213,7 +211,6 @@ static int blkif_queue_request(struct request *req) .last_sect = lsect }; ring_req->nr_segments++; - } } info->ring.req_prod_pvt++; diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index ae8e1a64b8ad..a775450d7a38 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -606,13 +606,12 @@ static void idefloppy_input_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, uns { struct request *rq = pc->rq; struct bio_vec *bvec; - struct bio *bio; + struct req_iterator iter; unsigned long flags; char *data; - int count, i, done = 0; + int count, done = 0; - rq_for_each_bio(bio, rq) { - bio_for_each_segment(bvec, bio, i) { + rq_for_each_segment(bvec, rq, iter) { if (!bcount) break; @@ -625,7 +624,6 @@ static void idefloppy_input_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, uns bcount -= count; pc->b_count += count; done += count; - } } idefloppy_do_end_request(drive, 1, done >> 9); @@ -639,14 +637,13 @@ static void idefloppy_input_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, uns static void idefloppy_output_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, unsigned int bcount) { struct request *rq = pc->rq; - struct bio *bio; + struct req_iterator iter; struct bio_vec *bvec; unsigned long flags; - int count, i, done = 0; + int count, done = 0; char *data; - rq_for_each_bio(bio, rq) { - bio_for_each_segment(bvec, bio, i) { + rq_for_each_segment(bvec, rq, iter) { if (!bcount) break; @@ -659,7 +656,6 @@ static void idefloppy_output_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, un bcount -= count; pc->b_count += count; done += count; - } } idefloppy_do_end_request(drive, 1, done >> 9); diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c index d32c60dbdd82..6bb9676f203e 100644 --- a/drivers/s390/block/dasd_diag.c +++ b/drivers/s390/block/dasd_diag.c @@ -472,14 +472,13 @@ dasd_diag_build_cp(struct dasd_device * device, struct request *req) struct dasd_ccw_req *cqr; struct dasd_diag_req *dreq; struct dasd_diag_bio *dbio; - struct bio *bio; + struct req_iterator iter; struct bio_vec *bv; char *dst; unsigned int count, datasize; sector_t recid, first_rec, last_rec; unsigned int blksize, off; unsigned char rw_cmd; - int i; if (rq_data_dir(req) == READ) rw_cmd = MDSK_READ_REQ; @@ -493,13 +492,11 @@ dasd_diag_build_cp(struct dasd_device * device, struct request *req) last_rec = (req->sector + req->nr_sectors - 1) >> device->s2b_shift; /* Check struct bio and count the number of blocks for the request. */ count = 0; - rq_for_each_bio(bio, req) { - bio_for_each_segment(bv, bio, i) { + rq_for_each_segment(bv, req, iter) { if (bv->bv_len & (blksize - 1)) /* Fba can only do full blocks. */ return ERR_PTR(-EINVAL); count += bv->bv_len >> (device->s2b_shift + 9); - } } /* Paranoia. */ if (count != last_rec - first_rec + 1) @@ -516,8 +513,7 @@ dasd_diag_build_cp(struct dasd_device * device, struct request *req) dreq->block_count = count; dbio = dreq->bio; recid = first_rec; - rq_for_each_bio(bio, req) { - bio_for_each_segment(bv, bio, i) { + rq_for_each_segment(bv, req, iter) { dst = page_address(bv->bv_page) + bv->bv_offset; for (off = 0; off < bv->bv_len; off += blksize) { memset(dbio, 0, sizeof (struct dasd_diag_bio)); @@ -528,7 +524,6 @@ dasd_diag_build_cp(struct dasd_device * device, struct request *req) dst += blksize; recid++; } - } } cqr->retries = DIAG_MAX_RETRIES; cqr->buildclk = get_clock(); diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index ea63ba7828f9..36ba45849874 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -1176,7 +1176,7 @@ dasd_eckd_build_cp(struct dasd_device * device, struct request *req) struct LO_eckd_data *LO_data; struct dasd_ccw_req *cqr; struct ccw1 *ccw; - struct bio *bio; + struct req_iterator iter; struct bio_vec *bv; char *dst; unsigned int blksize, blk_per_trk, off; @@ -1185,7 +1185,6 @@ dasd_eckd_build_cp(struct dasd_device * device, struct request *req) sector_t first_trk, last_trk; unsigned int first_offs, last_offs; unsigned char cmd, rcmd; - int i; private = (struct dasd_eckd_private *) device->private; if (rq_data_dir(req) == READ) @@ -1206,8 +1205,7 @@ dasd_eckd_build_cp(struct dasd_device * device, struct request *req) /* Check struct bio and count the number of blocks for the request. */ count = 0; cidaw = 0; - rq_for_each_bio(bio, req) { - bio_for_each_segment(bv, bio, i) { + rq_for_each_segment(bv, req, iter) { if (bv->bv_len & (blksize - 1)) /* Eckd can only do full blocks. */ return ERR_PTR(-EINVAL); @@ -1217,7 +1215,6 @@ dasd_eckd_build_cp(struct dasd_device * device, struct request *req) bv->bv_len)) cidaw += bv->bv_len >> (device->s2b_shift + 9); #endif - } } /* Paranoia. */ if (count != last_rec - first_rec + 1) @@ -1257,7 +1254,7 @@ dasd_eckd_build_cp(struct dasd_device * device, struct request *req) locate_record(ccw++, LO_data++, first_trk, first_offs + 1, last_rec - recid + 1, cmd, device, blksize); } - rq_for_each_bio(bio, req) bio_for_each_segment(bv, bio, i) { + rq_for_each_segment(bv, req, iter) { dst = page_address(bv->bv_page) + bv->bv_offset; if (dasd_page_cache) { char *copy = kmem_cache_alloc(dasd_page_cache, @@ -1328,12 +1325,12 @@ dasd_eckd_free_cp(struct dasd_ccw_req *cqr, struct request *req) { struct dasd_eckd_private *private; struct ccw1 *ccw; - struct bio *bio; + struct req_iterator iter; struct bio_vec *bv; char *dst, *cda; unsigned int blksize, blk_per_trk, off; sector_t recid; - int i, status; + int status; if (!dasd_page_cache) goto out; @@ -1346,7 +1343,7 @@ dasd_eckd_free_cp(struct dasd_ccw_req *cqr, struct request *req) ccw++; if (private->uses_cdl == 0 || recid > 2*blk_per_trk) ccw++; - rq_for_each_bio(bio, req) bio_for_each_segment(bv, bio, i) { + rq_for_each_segment(bv, req, iter) { dst = page_address(bv->bv_page) + bv->bv_offset; for (off = 0; off < bv->bv_len; off += blksize) { /* Skip locate record. */ diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c index da16ead8aff2..119b8d2d5f17 100644 --- a/drivers/s390/block/dasd_fba.c +++ b/drivers/s390/block/dasd_fba.c @@ -234,14 +234,13 @@ dasd_fba_build_cp(struct dasd_device * device, struct request *req) struct LO_fba_data *LO_data; struct dasd_ccw_req *cqr; struct ccw1 *ccw; - struct bio *bio; + struct req_iterator iter; struct bio_vec *bv; char *dst; int count, cidaw, cplength, datasize; sector_t recid, first_rec, last_rec; unsigned int blksize, off; unsigned char cmd; - int i; private = (struct dasd_fba_private *) device->private; if (rq_data_dir(req) == READ) { @@ -257,8 +256,7 @@ dasd_fba_build_cp(struct dasd_device * device, struct request *req) /* Check struct bio and count the number of blocks for the request. */ count = 0; cidaw = 0; - rq_for_each_bio(bio, req) { - bio_for_each_segment(bv, bio, i) { + rq_for_each_segment(bv, req, iter) { if (bv->bv_len & (blksize - 1)) /* Fba can only do full blocks. */ return ERR_PTR(-EINVAL); @@ -268,7 +266,6 @@ dasd_fba_build_cp(struct dasd_device * device, struct request *req) bv->bv_len)) cidaw += bv->bv_len / blksize; #endif - } } /* Paranoia. */ if (count != last_rec - first_rec + 1) @@ -304,7 +301,7 @@ dasd_fba_build_cp(struct dasd_device * device, struct request *req) locate_record(ccw++, LO_data++, rq_data_dir(req), 0, count); } recid = first_rec; - rq_for_each_bio(bio, req) bio_for_each_segment(bv, bio, i) { + rq_for_each_segment(bv, req, iter) { dst = page_address(bv->bv_page) + bv->bv_offset; if (dasd_page_cache) { char *copy = kmem_cache_alloc(dasd_page_cache, @@ -359,11 +356,11 @@ dasd_fba_free_cp(struct dasd_ccw_req *cqr, struct request *req) { struct dasd_fba_private *private; struct ccw1 *ccw; - struct bio *bio; + struct req_iterator iter; struct bio_vec *bv; char *dst, *cda; unsigned int blksize, off; - int i, status; + int status; if (!dasd_page_cache) goto out; @@ -374,7 +371,7 @@ dasd_fba_free_cp(struct dasd_ccw_req *cqr, struct request *req) ccw++; if (private->rdc_data.mode.bits.data_chain != 0) ccw++; - rq_for_each_bio(bio, req) bio_for_each_segment(bv, bio, i) { + rq_for_each_segment(bv, req, iter) { dst = page_address(bv->bv_page) + bv->bv_offset; for (off = 0; off < bv->bv_len; off += blksize) { /* Skip locate record. */ diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c index 80e7a537e7d2..ea3e6a345c89 100644 --- a/drivers/s390/char/tape_34xx.c +++ b/drivers/s390/char/tape_34xx.c @@ -1134,21 +1134,18 @@ tape_34xx_bread(struct tape_device *device, struct request *req) { struct tape_request *request; struct ccw1 *ccw; - int count = 0, i; + int count = 0; unsigned off; char *dst; struct bio_vec *bv; - struct bio *bio; + struct req_iterator iter; struct tape_34xx_block_id * start_block; DBF_EVENT(6, "xBREDid:"); /* Count the number of blocks for the request. */ - rq_for_each_bio(bio, req) { - bio_for_each_segment(bv, bio, i) { - count += bv->bv_len >> (TAPEBLOCK_HSEC_S2B + 9); - } - } + rq_for_each_segment(bv, req, iter) + count += bv->bv_len >> (TAPEBLOCK_HSEC_S2B + 9); /* Allocate the ccw request. */ request = tape_alloc_request(3+count+1, 8); @@ -1175,8 +1172,7 @@ tape_34xx_bread(struct tape_device *device, struct request *req) ccw = tape_ccw_cc(ccw, NOP, 0, NULL); ccw = tape_ccw_cc(ccw, NOP, 0, NULL); - rq_for_each_bio(bio, req) { - bio_for_each_segment(bv, bio, i) { + rq_for_each_segment(bv, req, iter) { dst = kmap(bv->bv_page) + bv->bv_offset; for (off = 0; off < bv->bv_len; off += TAPEBLOCK_HSEC_SIZE) { @@ -1187,7 +1183,6 @@ tape_34xx_bread(struct tape_device *device, struct request *req) ccw++; dst += TAPEBLOCK_HSEC_SIZE; } - } } ccw = tape_ccw_end(ccw, NOP, 0, NULL); diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c index 7e2b2ab49264..b16ad7a7631d 100644 --- a/drivers/s390/char/tape_3590.c +++ b/drivers/s390/char/tape_3590.c @@ -623,21 +623,19 @@ tape_3590_bread(struct tape_device *device, struct request *req) { struct tape_request *request; struct ccw1 *ccw; - int count = 0, start_block, i; + int count = 0, start_block; unsigned off; char *dst; struct bio_vec *bv; - struct bio *bio; + struct req_iterator iter; DBF_EVENT(6, "xBREDid:"); start_block = req->sector >> TAPEBLOCK_HSEC_S2B; DBF_EVENT(6, "start_block = %i\n", start_block); - rq_for_each_bio(bio, req) { - bio_for_each_segment(bv, bio, i) { - count += bv->bv_len >> (TAPEBLOCK_HSEC_S2B + 9); - } - } + rq_for_each_segment(bv, req, iter) + count += bv->bv_len >> (TAPEBLOCK_HSEC_S2B + 9); + request = tape_alloc_request(2 + count + 1, 4); if (IS_ERR(request)) return request; @@ -653,8 +651,7 @@ tape_3590_bread(struct tape_device *device, struct request *req) */ ccw = tape_ccw_cc(ccw, NOP, 0, NULL); - rq_for_each_bio(bio, req) { - bio_for_each_segment(bv, bio, i) { + rq_for_each_segment(bv, req, iter) { dst = page_address(bv->bv_page) + bv->bv_offset; for (off = 0; off < bv->bv_len; off += TAPEBLOCK_HSEC_SIZE) { @@ -667,7 +664,6 @@ tape_3590_bread(struct tape_device *device, struct request *req) } if (off > bv->bv_len) BUG(); - } } ccw = tape_ccw_end(ccw, NOP, 0, NULL); DBF_EVENT(6, "xBREDccwg\n"); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index b126c6f68e27..a4b13b8a9d09 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -637,10 +637,23 @@ static inline void blk_queue_bounce(struct request_queue *q, struct bio **bio) } #endif /* CONFIG_MMU */ -#define rq_for_each_bio(_bio, rq) \ +struct req_iterator { + int i; + struct bio *bio; +}; + +/* This should not be used directly - use rq_for_each_segment */ +#define __rq_for_each_bio(_bio, rq) \ if ((rq->bio)) \ for (_bio = (rq)->bio; _bio; _bio = _bio->bi_next) +#define rq_for_each_segment(bvl, _rq, _iter) \ + __rq_for_each_bio(_iter.bio, _rq) \ + bio_for_each_segment(bvl, _iter.bio, _iter.i) + +#define rq_iter_last(rq, _iter) \ + (_iter.bio->bi_next == NULL && _iter.i == _iter.bio->bi_vcnt-1) + extern int blk_register_queue(struct gendisk *disk); extern void blk_unregister_queue(struct gendisk *disk); extern void register_disk(struct gendisk *dev); From eea9befaccb8d43ce89585d612159761c978f056 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 16 Aug 2007 13:31:26 +0200 Subject: [PATCH 03/37] Fix various abuse of bio fields in umem.c umem.c: advances bi_idx and bi_sector to track where it is up to. But it is only ever doing this on one bio, so the updated fields can easily be kept elsewhere (current_*). updates bi_size, but never uses the updated values, so this isn't needed. reuses bi_phys_segments to count how many iovecs have been completely. As the completion happens sequentiually, we can store this information outside the bio too. Signed-off-by: Neil Brown diff .prev/drivers/block/umem.c ./drivers/block/umem.c Signed-off-by: Jens Axboe --- drivers/block/umem.c | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/drivers/block/umem.c b/drivers/block/umem.c index 6b7c02d6360d..c378e285d708 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c @@ -113,6 +113,8 @@ struct cardinfo { * have been written */ struct bio *bio, *currentbio, **biotail; + int current_idx; + sector_t current_sector; struct request_queue *queue; @@ -121,6 +123,7 @@ struct cardinfo { struct mm_dma_desc *desc; int cnt, headcnt; struct bio *bio, **biotail; + int idx; } mm_pages[2]; #define DESC_PER_PAGE ((PAGE_SIZE*2)/sizeof(struct mm_dma_desc)) @@ -380,12 +383,16 @@ static int add_bio(struct cardinfo *card) dma_addr_t dma_handle; int offset; struct bio *bio; + struct bio_vec *vec; + int idx; int rw; int len; bio = card->currentbio; if (!bio && card->bio) { card->currentbio = card->bio; + card->current_idx = card->bio->bi_idx; + card->current_sector = card->bio->bi_sector; card->bio = card->bio->bi_next; if (card->bio == NULL) card->biotail = &card->bio; @@ -394,15 +401,17 @@ static int add_bio(struct cardinfo *card) } if (!bio) return 0; + idx = card->current_idx; rw = bio_rw(bio); if (card->mm_pages[card->Ready].cnt >= DESC_PER_PAGE) return 0; - len = bio_iovec(bio)->bv_len; - dma_handle = pci_map_page(card->dev, - bio_page(bio), - bio_offset(bio), + vec = bio_iovec_idx(bio, idx); + len = vec->bv_len; + dma_handle = pci_map_page(card->dev, + vec->bv_page, + vec->bv_offset, len, (rw==READ) ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE); @@ -410,6 +419,8 @@ static int add_bio(struct cardinfo *card) p = &card->mm_pages[card->Ready]; desc = &p->desc[p->cnt]; p->cnt++; + if (p->bio == NULL) + p->idx = idx; if ((p->biotail) != &bio->bi_next) { *(p->biotail) = bio; p->biotail = &(bio->bi_next); @@ -419,7 +430,7 @@ static int add_bio(struct cardinfo *card) desc->data_dma_handle = dma_handle; desc->pci_addr = cpu_to_le64((u64)desc->data_dma_handle); - desc->local_addr= cpu_to_le64(bio->bi_sector << 9); + desc->local_addr = cpu_to_le64(card->current_sector << 9); desc->transfer_size = cpu_to_le32(len); offset = ( ((char*)&desc->sem_control_bits) - ((char*)p->desc)); desc->sem_addr = cpu_to_le64((u64)(p->page_dma+offset)); @@ -435,10 +446,10 @@ static int add_bio(struct cardinfo *card) desc->control_bits |= cpu_to_le32(DMASCR_TRANSFER_READ); desc->sem_control_bits = desc->control_bits; - bio->bi_sector += (len>>9); - bio->bi_size -= len; - bio->bi_idx++; - if (bio->bi_idx >= bio->bi_vcnt) + card->current_sector += (len >> 9); + idx++; + card->current_idx = idx; + if (idx >= bio->bi_vcnt) card->currentbio = NULL; return 1; @@ -474,10 +485,12 @@ static void process_page(unsigned long data) last=1; } page->headcnt++; - idx = bio->bi_phys_segments; - bio->bi_phys_segments++; - if (bio->bi_phys_segments >= bio->bi_vcnt) + idx = page->idx; + page->idx++; + if (page->idx >= bio->bi_vcnt) { page->bio = bio->bi_next; + page->idx = page->bio->bi_idx; + } pci_unmap_page(card->dev, desc->data_dma_handle, bio_iovec_idx(bio,idx)->bv_len, @@ -547,7 +560,6 @@ static int mm_make_request(struct request_queue *q, struct bio *bio) pr_debug("mm_make_request %llu %u\n", (unsigned long long)bio->bi_sector, bio->bi_size); - bio->bi_phys_segments = bio->bi_idx; /* count of completed segments*/ spin_lock_irq(&card->lock); *card->biotail = bio; bio->bi_next = NULL; From 3001ca77128273cc5634d79f5306ce2e5a14ec41 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 16 Aug 2007 13:31:27 +0200 Subject: [PATCH 04/37] New function blk_req_append_bio ll_back_merge_fn is currently exported to SCSI where is it used, together with blk_rq_bio_prep, in exactly the same way these functions are used in __blk_rq_map_user. So move the common code into a new function (blk_rq_append_bio), and don't export ll_back_merge_fn any longer. Signed-off-by: Neil Brown diff .prev/block/ll_rw_blk.c ./block/ll_rw_blk.c Signed-off-by: Jens Axboe --- block/ll_rw_blk.c | 38 ++++++++++++++++++++++---------------- drivers/scsi/scsi_lib.c | 11 +---------- include/linux/blkdev.h | 4 ++-- 3 files changed, 25 insertions(+), 28 deletions(-) diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 094c0fa5c405..2de9bad1d042 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -1441,7 +1441,8 @@ static inline int ll_new_hw_segment(struct request_queue *q, return 1; } -int ll_back_merge_fn(struct request_queue *q, struct request *req, struct bio *bio) +static int ll_back_merge_fn(struct request_queue *q, struct request *req, + struct bio *bio) { unsigned short max_sectors; int len; @@ -1477,7 +1478,6 @@ int ll_back_merge_fn(struct request_queue *q, struct request *req, struct bio *b return ll_new_hw_segment(q, req, bio); } -EXPORT_SYMBOL(ll_back_merge_fn); static int ll_front_merge_fn(struct request_queue *q, struct request *req, struct bio *bio) @@ -2367,6 +2367,23 @@ static int __blk_rq_unmap_user(struct bio *bio) return ret; } +int blk_rq_append_bio(struct request_queue *q, struct request *rq, + struct bio *bio) +{ + if (!rq->bio) + blk_rq_bio_prep(q, rq, bio); + else if (!ll_back_merge_fn(q, rq, bio)) + return -EINVAL; + else { + rq->biotail->bi_next = bio; + rq->biotail = bio; + + rq->data_len += bio->bi_size; + } + return 0; +} +EXPORT_SYMBOL(blk_rq_append_bio); + static int __blk_rq_map_user(struct request_queue *q, struct request *rq, void __user *ubuf, unsigned int len) { @@ -2398,21 +2415,10 @@ static int __blk_rq_map_user(struct request_queue *q, struct request *rq, */ bio_get(bio); - if (!rq->bio) - blk_rq_bio_prep(q, rq, bio); - else if (!ll_back_merge_fn(q, rq, bio)) { - ret = -EINVAL; - goto unmap_bio; - } else { - rq->biotail->bi_next = bio; - rq->biotail = bio; + ret = blk_rq_append_bio(q, rq, bio); + if (!ret) + return bio->bi_size; - rq->data_len += bio->bi_size; - } - - return bio->bi_size; - -unmap_bio: /* if it was boucned we must call the end io function */ bio_endio(bio, bio->bi_size, 0); __blk_rq_unmap_user(orig_bio); diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index a417a6ff9f97..59b398530295 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -263,16 +263,7 @@ static int scsi_merge_bio(struct request *rq, struct bio *bio) bio->bi_rw |= (1 << BIO_RW); blk_queue_bounce(q, &bio); - if (!rq->bio) - blk_rq_bio_prep(q, rq, bio); - else if (!ll_back_merge_fn(q, rq, bio)) - return -EINVAL; - else { - rq->biotail->bi_next = bio; - rq->biotail = bio; - } - - return 0; + return blk_rq_append_bio(q, rq, bio); } static int scsi_bi_endio(struct bio *bio, unsigned int bytes_done, int error) diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index a4b13b8a9d09..3021a5b1d392 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -675,8 +675,8 @@ extern int sg_scsi_ioctl(struct file *, struct request_queue *, /* * Temporary export, until SCSI gets fixed up. */ -extern int ll_back_merge_fn(struct request_queue *, struct request *, - struct bio *); +extern int blk_rq_append_bio(struct request_queue *q, struct request *rq, + struct bio *bio); /* * A queue has just exitted congestion. Note this in the global counter of From 66846572bfb4ec62bcba260028cbbcbdb77bd636 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 16 Aug 2007 13:31:28 +0200 Subject: [PATCH 05/37] Stop exporting blk_rq_bio_prep blk_rq_bio_prep is exported for use in exactly one place. That place can benefit from using the new blk_rq_append_bio instead. So - change dm-emc to call blk_rq_append_bio - stop exporting blk_rq_bio_prep, and - initialise rq_disk in blk_rq_bio_prep, as dm-emc needs it. Signed-off-by: Neil Brown diff .prev/block/ll_rw_blk.c ./block/ll_rw_blk.c Signed-off-by: Jens Axboe --- block/ll_rw_blk.c | 11 +++++++---- drivers/md/dm-emc.c | 10 +--------- include/linux/blkdev.h | 1 - 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 2de9bad1d042..eb27b335d238 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -43,6 +43,8 @@ static void init_request_from_bio(struct request *req, struct bio *bio); static int __make_request(struct request_queue *q, struct bio *bio); static struct io_context *current_io_context(gfp_t gfp_flags, int node); static void blk_recalc_rq_segments(struct request *rq); +static void blk_rq_bio_prep(struct request_queue *q, struct request *rq, + struct bio *bio); /* * For the allocated request tables @@ -3665,8 +3667,8 @@ void end_request(struct request *req, int uptodate) EXPORT_SYMBOL(end_request); -void blk_rq_bio_prep(struct request_queue *q, struct request *rq, - struct bio *bio) +static void blk_rq_bio_prep(struct request_queue *q, struct request *rq, + struct bio *bio) { /* first two bits are identical in rq->cmd_flags and bio->bi_rw */ rq->cmd_flags |= (bio->bi_rw & 3); @@ -3680,9 +3682,10 @@ void blk_rq_bio_prep(struct request_queue *q, struct request *rq, rq->data_len = bio->bi_size; rq->bio = rq->biotail = bio; -} -EXPORT_SYMBOL(blk_rq_bio_prep); + if (bio->bi_bdev) + rq->rq_disk = bio->bi_bdev->bd_disk; +} int kblockd_schedule_work(struct work_struct *work) { diff --git a/drivers/md/dm-emc.c b/drivers/md/dm-emc.c index 265c467854da..71cc858b7860 100644 --- a/drivers/md/dm-emc.c +++ b/drivers/md/dm-emc.c @@ -109,15 +109,7 @@ static struct request *get_failover_req(struct emc_handler *h, return NULL; } - rq->bio = rq->biotail = bio; - blk_rq_bio_prep(q, rq, bio); - - rq->rq_disk = bdev->bd_contains->bd_disk; - - /* bio backed don't set data */ - rq->buffer = rq->data = NULL; - /* rq data_len used for pc cmd's request_bufflen */ - rq->data_len = bio->bi_size; + blk_rq_append_bio(q, rq, bio); rq->sense = h->sense; memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 3021a5b1d392..492ac946391e 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -823,7 +823,6 @@ static inline struct request *blk_map_queue_find_tag(struct blk_queue_tag *bqt, return bqt->tag_index[tag]; } -extern void blk_rq_bio_prep(struct request_queue *, struct request *, struct bio *); extern int blkdev_issue_flush(struct block_device *, sector_t *); #define MAX_PHYS_SEGMENTS 128 From bc1c56fde6dd1c85e2047c276456c07bd4508b5c Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 16 Aug 2007 13:31:30 +0200 Subject: [PATCH 06/37] Share code between init_request_from_bio and blk_rq_bio_prep These have very similar functions and should share code where possible. Signed-off-by: Neil Brown diff .prev/block/ll_rw_blk.c ./block/ll_rw_blk.c Signed-off-by: Jens Axboe --- block/ll_rw_blk.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index eb27b335d238..e0608c4ecc23 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -2941,15 +2941,9 @@ static void init_request_from_bio(struct request *req, struct bio *bio) req->errors = 0; req->hard_sector = req->sector = bio->bi_sector; - req->hard_nr_sectors = req->nr_sectors = bio_sectors(bio); - req->current_nr_sectors = req->hard_cur_sectors = bio_cur_sectors(bio); - req->nr_phys_segments = bio_phys_segments(req->q, bio); - req->nr_hw_segments = bio_hw_segments(req->q, bio); - req->buffer = bio_data(bio); /* see ->buffer comment above */ - req->bio = req->biotail = bio; req->ioprio = bio_prio(bio); - req->rq_disk = bio->bi_bdev->bd_disk; req->start_time = jiffies; + blk_rq_bio_prep(req->q, req, bio); } static int __make_request(struct request_queue *q, struct bio *bio) From 6c92e699b56287da582ccb12a64b959b6d6109ba Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 16 Aug 2007 13:43:12 +0200 Subject: [PATCH 07/37] Fixup rq_for_each_segment() indentation Remove one level of nesting where appropriate. Signed-off-by: Jens Axboe --- block/ll_rw_blk.c | 34 +++++++++++++-------------- drivers/block/lguest_blk.c | 24 +++++++++---------- drivers/block/nbd.c | 43 ++++++++++++++++------------------ drivers/block/ps3disk.c | 19 +++++++-------- drivers/block/xen-blkfront.c | 23 +++++++++--------- drivers/ide/ide-floppy.c | 36 ++++++++++++++-------------- drivers/s390/block/dasd_diag.c | 28 +++++++++++----------- drivers/s390/block/dasd_eckd.c | 13 +++++----- drivers/s390/block/dasd_fba.c | 13 +++++----- drivers/s390/char/tape_34xx.c | 19 +++++++-------- drivers/s390/char/tape_3590.c | 23 +++++++++--------- 11 files changed, 133 insertions(+), 142 deletions(-) diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index e0608c4ecc23..c6b2a477d33e 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -1364,28 +1364,28 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq, */ bvprv = NULL; rq_for_each_segment(bvec, rq, iter) { - int nbytes = bvec->bv_len; + int nbytes = bvec->bv_len; - if (bvprv && cluster) { - if (sg[nsegs - 1].length + nbytes > q->max_segment_size) - goto new_segment; + if (bvprv && cluster) { + if (sg[nsegs - 1].length + nbytes > q->max_segment_size) + goto new_segment; - if (!BIOVEC_PHYS_MERGEABLE(bvprv, bvec)) - goto new_segment; - if (!BIOVEC_SEG_BOUNDARY(q, bvprv, bvec)) - goto new_segment; + if (!BIOVEC_PHYS_MERGEABLE(bvprv, bvec)) + goto new_segment; + if (!BIOVEC_SEG_BOUNDARY(q, bvprv, bvec)) + goto new_segment; - sg[nsegs - 1].length += nbytes; - } else { + sg[nsegs - 1].length += nbytes; + } else { new_segment: - memset(&sg[nsegs],0,sizeof(struct scatterlist)); - sg[nsegs].page = bvec->bv_page; - sg[nsegs].length = nbytes; - sg[nsegs].offset = bvec->bv_offset; + memset(&sg[nsegs],0,sizeof(struct scatterlist)); + sg[nsegs].page = bvec->bv_page; + sg[nsegs].length = nbytes; + sg[nsegs].offset = bvec->bv_offset; - nsegs++; - } - bvprv = bvec; + nsegs++; + } + bvprv = bvec; } /* segments in rq */ return nsegs; diff --git a/drivers/block/lguest_blk.c b/drivers/block/lguest_blk.c index 1e838ae60a60..fa8e42341b87 100644 --- a/drivers/block/lguest_blk.c +++ b/drivers/block/lguest_blk.c @@ -147,18 +147,18 @@ static unsigned int req_to_dma(struct request *req, struct lguest_dma *dma) struct bio_vec *bvec; rq_for_each_segment(bvec, req, iter) { - /* We told the block layer not to give us too many. */ - BUG_ON(i == LGUEST_MAX_DMA_SECTIONS); - /* If we had a zero-length segment, it would look like - * the end of the data referred to by the "struct - * lguest_dma", so make sure that doesn't happen. */ - BUG_ON(!bvec->bv_len); - /* Convert page & offset to a physical address */ - dma->addr[i] = page_to_phys(bvec->bv_page) - + bvec->bv_offset; - dma->len[i] = bvec->bv_len; - len += bvec->bv_len; - i++; + /* We told the block layer not to give us too many. */ + BUG_ON(i == LGUEST_MAX_DMA_SECTIONS); + /* If we had a zero-length segment, it would look like + * the end of the data referred to by the "struct + * lguest_dma", so make sure that doesn't happen. */ + BUG_ON(!bvec->bv_len); + /* Convert page & offset to a physical address */ + dma->addr[i] = page_to_phys(bvec->bv_page) + + bvec->bv_offset; + dma->len[i] = bvec->bv_len; + len += bvec->bv_len; + i++; } /* If the array isn't full, we mark the end with a 0 length */ if (i < LGUEST_MAX_DMA_SECTIONS) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 228b2ff577aa..be5ec3a9b1fc 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -212,19 +212,17 @@ static int nbd_send_req(struct nbd_device *lo, struct request *req) * whether to set MSG_MORE or not... */ rq_for_each_segment(bvec, req, iter) { - flags = 0; - if (!rq_iter_last(req, iter)) - flags = MSG_MORE; - dprintk(DBG_TX, "%s: request %p: sending %d bytes data\n", - lo->disk->disk_name, req, - bvec->bv_len); - result = sock_send_bvec(sock, bvec, flags); - if (result <= 0) { - printk(KERN_ERR "%s: Send data failed (result %d)\n", - lo->disk->disk_name, - result); - goto error_out; - } + flags = 0; + if (!rq_iter_last(req, iter)) + flags = MSG_MORE; + dprintk(DBG_TX, "%s: request %p: sending %d bytes data\n", + lo->disk->disk_name, req, bvec->bv_len); + result = sock_send_bvec(sock, bvec, flags); + if (result <= 0) { + printk(KERN_ERR "%s: Send data failed (result %d)\n", + lo->disk->disk_name, result); + goto error_out; + } } } return 0; @@ -323,16 +321,15 @@ static struct request *nbd_read_stat(struct nbd_device *lo) struct bio_vec *bvec; rq_for_each_segment(bvec, req, iter) { - result = sock_recv_bvec(sock, bvec); - if (result <= 0) { - printk(KERN_ERR "%s: Receive data failed (result %d)\n", - lo->disk->disk_name, - result); - req->errors++; - return req; - } - dprintk(DBG_RX, "%s: request %p: got %d bytes data\n", - lo->disk->disk_name, req, bvec->bv_len); + result = sock_recv_bvec(sock, bvec); + if (result <= 0) { + printk(KERN_ERR "%s: Receive data failed (result %d)\n", + lo->disk->disk_name, result); + req->errors++; + return req; + } + dprintk(DBG_RX, "%s: request %p: got %d bytes data\n", + lo->disk->disk_name, req, bvec->bv_len); } } return req; diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c index 8953e7ce0016..06d0552cf49c 100644 --- a/drivers/block/ps3disk.c +++ b/drivers/block/ps3disk.c @@ -105,16 +105,15 @@ static void ps3disk_scatter_gather(struct ps3_storage_device *dev, bio_sectors(iter.bio), (unsigned long)iter.bio->bi_sector); - size = bvec->bv_len; - buf = bvec_kmap_irq(bvec, &flags); - if (gather) - memcpy(dev->bounce_buf+offset, buf, size); - else - memcpy(buf, dev->bounce_buf+offset, size); - offset += size; - flush_kernel_dcache_page(bvec->bv_page); - bvec_kunmap_irq(bvec, &flags); - + size = bvec->bv_len; + buf = bvec_kmap_irq(bvec, &flags); + if (gather) + memcpy(dev->bounce_buf+offset, buf, size); + else + memcpy(buf, dev->bounce_buf+offset, size); + offset += size; + flush_kernel_dcache_page(bvec->bv_page); + bvec_kunmap_irq(bvec, &flags); i++; } } diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 6af250113c2a..2bdebcb3ff16 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -186,31 +186,30 @@ static int blkif_queue_request(struct request *req) ring_req->nr_segments = 0; rq_for_each_segment(bvec, req, iter) { - BUG_ON(ring_req->nr_segments - == BLKIF_MAX_SEGMENTS_PER_REQUEST); - buffer_mfn = pfn_to_mfn(page_to_pfn(bvec->bv_page)); - fsect = bvec->bv_offset >> 9; - lsect = fsect + (bvec->bv_len >> 9) - 1; - /* install a grant reference. */ - ref = gnttab_claim_grant_reference(&gref_head); - BUG_ON(ref == -ENOSPC); + BUG_ON(ring_req->nr_segments == BLKIF_MAX_SEGMENTS_PER_REQUEST); + buffer_mfn = pfn_to_mfn(page_to_pfn(bvec->bv_page)); + fsect = bvec->bv_offset >> 9; + lsect = fsect + (bvec->bv_len >> 9) - 1; + /* install a grant reference. */ + ref = gnttab_claim_grant_reference(&gref_head); + BUG_ON(ref == -ENOSPC); - gnttab_grant_foreign_access_ref( + gnttab_grant_foreign_access_ref( ref, info->xbdev->otherend_id, buffer_mfn, rq_data_dir(req) ); - info->shadow[id].frame[ring_req->nr_segments] = + info->shadow[id].frame[ring_req->nr_segments] = mfn_to_pfn(buffer_mfn); - ring_req->seg[ring_req->nr_segments] = + ring_req->seg[ring_req->nr_segments] = (struct blkif_request_segment) { .gref = ref, .first_sect = fsect, .last_sect = lsect }; - ring_req->nr_segments++; + ring_req->nr_segments++; } info->ring.req_prod_pvt++; diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index a775450d7a38..04a357808f2e 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -612,18 +612,18 @@ static void idefloppy_input_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, uns int count, done = 0; rq_for_each_segment(bvec, rq, iter) { - if (!bcount) - break; + if (!bcount) + break; - count = min(bvec->bv_len, bcount); + count = min(bvec->bv_len, bcount); - data = bvec_kmap_irq(bvec, &flags); - drive->hwif->atapi_input_bytes(drive, data, count); - bvec_kunmap_irq(data, &flags); + data = bvec_kmap_irq(bvec, &flags); + drive->hwif->atapi_input_bytes(drive, data, count); + bvec_kunmap_irq(data, &flags); - bcount -= count; - pc->b_count += count; - done += count; + bcount -= count; + pc->b_count += count; + done += count; } idefloppy_do_end_request(drive, 1, done >> 9); @@ -644,18 +644,18 @@ static void idefloppy_output_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, un char *data; rq_for_each_segment(bvec, rq, iter) { - if (!bcount) - break; + if (!bcount) + break; - count = min(bvec->bv_len, bcount); + count = min(bvec->bv_len, bcount); - data = bvec_kmap_irq(bvec, &flags); - drive->hwif->atapi_output_bytes(drive, data, count); - bvec_kunmap_irq(data, &flags); + data = bvec_kmap_irq(bvec, &flags); + drive->hwif->atapi_output_bytes(drive, data, count); + bvec_kunmap_irq(data, &flags); - bcount -= count; - pc->b_count += count; - done += count; + bcount -= count; + pc->b_count += count; + done += count; } idefloppy_do_end_request(drive, 1, done >> 9); diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c index 6bb9676f203e..571320ab9e1a 100644 --- a/drivers/s390/block/dasd_diag.c +++ b/drivers/s390/block/dasd_diag.c @@ -493,10 +493,10 @@ dasd_diag_build_cp(struct dasd_device * device, struct request *req) /* Check struct bio and count the number of blocks for the request. */ count = 0; rq_for_each_segment(bv, req, iter) { - if (bv->bv_len & (blksize - 1)) - /* Fba can only do full blocks. */ - return ERR_PTR(-EINVAL); - count += bv->bv_len >> (device->s2b_shift + 9); + if (bv->bv_len & (blksize - 1)) + /* Fba can only do full blocks. */ + return ERR_PTR(-EINVAL); + count += bv->bv_len >> (device->s2b_shift + 9); } /* Paranoia. */ if (count != last_rec - first_rec + 1) @@ -514,16 +514,16 @@ dasd_diag_build_cp(struct dasd_device * device, struct request *req) dbio = dreq->bio; recid = first_rec; rq_for_each_segment(bv, req, iter) { - dst = page_address(bv->bv_page) + bv->bv_offset; - for (off = 0; off < bv->bv_len; off += blksize) { - memset(dbio, 0, sizeof (struct dasd_diag_bio)); - dbio->type = rw_cmd; - dbio->block_number = recid + 1; - dbio->buffer = dst; - dbio++; - dst += blksize; - recid++; - } + dst = page_address(bv->bv_page) + bv->bv_offset; + for (off = 0; off < bv->bv_len; off += blksize) { + memset(dbio, 0, sizeof (struct dasd_diag_bio)); + dbio->type = rw_cmd; + dbio->block_number = recid + 1; + dbio->buffer = dst; + dbio++; + dst += blksize; + recid++; + } } cqr->retries = DIAG_MAX_RETRIES; cqr->buildclk = get_clock(); diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 36ba45849874..44adf8496bda 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -1206,14 +1206,13 @@ dasd_eckd_build_cp(struct dasd_device * device, struct request *req) count = 0; cidaw = 0; rq_for_each_segment(bv, req, iter) { - if (bv->bv_len & (blksize - 1)) - /* Eckd can only do full blocks. */ - return ERR_PTR(-EINVAL); - count += bv->bv_len >> (device->s2b_shift + 9); + if (bv->bv_len & (blksize - 1)) + /* Eckd can only do full blocks. */ + return ERR_PTR(-EINVAL); + count += bv->bv_len >> (device->s2b_shift + 9); #if defined(CONFIG_64BIT) - if (idal_is_needed (page_address(bv->bv_page), - bv->bv_len)) - cidaw += bv->bv_len >> (device->s2b_shift + 9); + if (idal_is_needed (page_address(bv->bv_page), bv->bv_len)) + cidaw += bv->bv_len >> (device->s2b_shift + 9); #endif } /* Paranoia. */ diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c index 119b8d2d5f17..1d95822e0b8e 100644 --- a/drivers/s390/block/dasd_fba.c +++ b/drivers/s390/block/dasd_fba.c @@ -257,14 +257,13 @@ dasd_fba_build_cp(struct dasd_device * device, struct request *req) count = 0; cidaw = 0; rq_for_each_segment(bv, req, iter) { - if (bv->bv_len & (blksize - 1)) - /* Fba can only do full blocks. */ - return ERR_PTR(-EINVAL); - count += bv->bv_len >> (device->s2b_shift + 9); + if (bv->bv_len & (blksize - 1)) + /* Fba can only do full blocks. */ + return ERR_PTR(-EINVAL); + count += bv->bv_len >> (device->s2b_shift + 9); #if defined(CONFIG_64BIT) - if (idal_is_needed (page_address(bv->bv_page), - bv->bv_len)) - cidaw += bv->bv_len / blksize; + if (idal_is_needed (page_address(bv->bv_page), bv->bv_len)) + cidaw += bv->bv_len / blksize; #endif } /* Paranoia. */ diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c index ea3e6a345c89..5b47e9cce75f 100644 --- a/drivers/s390/char/tape_34xx.c +++ b/drivers/s390/char/tape_34xx.c @@ -1173,16 +1173,15 @@ tape_34xx_bread(struct tape_device *device, struct request *req) ccw = tape_ccw_cc(ccw, NOP, 0, NULL); rq_for_each_segment(bv, req, iter) { - dst = kmap(bv->bv_page) + bv->bv_offset; - for (off = 0; off < bv->bv_len; - off += TAPEBLOCK_HSEC_SIZE) { - ccw->flags = CCW_FLAG_CC; - ccw->cmd_code = READ_FORWARD; - ccw->count = TAPEBLOCK_HSEC_SIZE; - set_normalized_cda(ccw, (void*) __pa(dst)); - ccw++; - dst += TAPEBLOCK_HSEC_SIZE; - } + dst = kmap(bv->bv_page) + bv->bv_offset; + for (off = 0; off < bv->bv_len; off += TAPEBLOCK_HSEC_SIZE) { + ccw->flags = CCW_FLAG_CC; + ccw->cmd_code = READ_FORWARD; + ccw->count = TAPEBLOCK_HSEC_SIZE; + set_normalized_cda(ccw, (void*) __pa(dst)); + ccw++; + dst += TAPEBLOCK_HSEC_SIZE; + } } ccw = tape_ccw_end(ccw, NOP, 0, NULL); diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c index b16ad7a7631d..9f244c591eeb 100644 --- a/drivers/s390/char/tape_3590.c +++ b/drivers/s390/char/tape_3590.c @@ -652,18 +652,17 @@ tape_3590_bread(struct tape_device *device, struct request *req) ccw = tape_ccw_cc(ccw, NOP, 0, NULL); rq_for_each_segment(bv, req, iter) { - dst = page_address(bv->bv_page) + bv->bv_offset; - for (off = 0; off < bv->bv_len; - off += TAPEBLOCK_HSEC_SIZE) { - ccw->flags = CCW_FLAG_CC; - ccw->cmd_code = READ_FORWARD; - ccw->count = TAPEBLOCK_HSEC_SIZE; - set_normalized_cda(ccw, (void *) __pa(dst)); - ccw++; - dst += TAPEBLOCK_HSEC_SIZE; - } - if (off > bv->bv_len) - BUG(); + dst = page_address(bv->bv_page) + bv->bv_offset; + for (off = 0; off < bv->bv_len; off += TAPEBLOCK_HSEC_SIZE) { + ccw->flags = CCW_FLAG_CC; + ccw->cmd_code = READ_FORWARD; + ccw->count = TAPEBLOCK_HSEC_SIZE; + set_normalized_cda(ccw, (void *) __pa(dst)); + ccw++; + dst += TAPEBLOCK_HSEC_SIZE; + } + if (off > bv->bv_len) + BUG(); } ccw = tape_ccw_end(ccw, NOP, 0, NULL); DBF_EVENT(6, "xBREDccwg\n"); From db47d475371bc85dd122112e957669cbbcc70dee Mon Sep 17 00:00:00 2001 From: Satyam Sharma Date: Thu, 23 Aug 2007 09:29:40 +0200 Subject: [PATCH 08/37] ll_rw_blk: blk_cpu_notifier should be __cpuinitdata blk_cpu_notifier is marked as __devinitdata, but __devinitdata need not be __init even if HOTPLUG_CPU=n, which wastes space. It should be marked __cpuinitdata, and the callback itself as __cpuinit. Signed-off-by: Satyam Sharma Signed-off-by: Andrew Morton Signed-off-by: Jens Axboe --- block/ll_rw_blk.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index c6b2a477d33e..3b2eff4e83a6 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -3555,7 +3555,7 @@ static void blk_done_softirq(struct softirq_action *h) } } -static int blk_cpu_notify(struct notifier_block *self, unsigned long action, +static int __cpuinit blk_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { /* @@ -3576,7 +3576,7 @@ static int blk_cpu_notify(struct notifier_block *self, unsigned long action, } -static struct notifier_block __devinitdata blk_cpu_notifier = { +static struct notifier_block blk_cpu_notifier __cpuinitdata = { .notifier_call = blk_cpu_notify, }; From 3317fedba9446465082bcc6ce1232451ad1d51ce Mon Sep 17 00:00:00 2001 From: Dhaval Giani Date: Thu, 23 Aug 2007 10:43:07 +0200 Subject: [PATCH 09/37] Corrections in Documentation/block/ioprio.txt The newer glibc does not allow system calls to be made via _syscallN() wrapper. They have to be made through syscall(). The ionice code used the older interface. Correcting it to use syscall. Signed-off-by: Dhaval Giani Signed-off-by: Jens Axboe --- Documentation/block/ioprio.txt | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Documentation/block/ioprio.txt b/Documentation/block/ioprio.txt index 1b930ef5a079..35e516b0b8a9 100644 --- a/Documentation/block/ioprio.txt +++ b/Documentation/block/ioprio.txt @@ -86,8 +86,15 @@ extern int sys_ioprio_get(int, int); #error "Unsupported arch" #endif -_syscall3(int, ioprio_set, int, which, int, who, int, ioprio); -_syscall2(int, ioprio_get, int, which, int, who); +static inline int ioprio_set(int which, int who, int ioprio) +{ + return syscall(__NR_ioprio_set, which, who, ioprio); +} + +static inline int ioprio_get(int which, int who) +{ + return syscall(__NR_ioprio_get, which, who); +} enum { IOPRIO_CLASS_NONE, From f5ff8422bbdd59f8c1f699df248e1b7a11073027 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 21 Sep 2007 09:19:54 +0200 Subject: [PATCH 10/37] Fix warnings with !CONFIG_BLOCK Hide everything in blkdev.h with CONFIG_BLOCK isn't set, and fixup the (few) files that fail to build because they were relying on blkdev.h pulling in extra includes for them. Signed-off-by: Jens Axboe --- fs/fs-writeback.c | 1 + include/linux/blkdev.h | 4 ++-- include/linux/writeback.h | 1 + kernel/sched.c | 1 + mm/readahead.c | 1 + 5 files changed, 6 insertions(+), 2 deletions(-) diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index a4b142a6a2c7..8d23b0b38717 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -14,6 +14,7 @@ */ #include +#include #include #include #include diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 492ac946391e..a0a998140447 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -1,6 +1,8 @@ #ifndef _LINUX_BLKDEV_H #define _LINUX_BLKDEV_H +#ifdef CONFIG_BLOCK + #include #include #include @@ -32,8 +34,6 @@ ) #endif -#ifdef CONFIG_BLOCK - struct scsi_ioctl_command; struct request_queue; diff --git a/include/linux/writeback.h b/include/linux/writeback.h index b4af6bcb7b7a..c7c3337c3a88 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h @@ -5,6 +5,7 @@ #define WRITEBACK_H #include +#include struct backing_dev_info; diff --git a/kernel/sched.c b/kernel/sched.c index 6107a0cd6325..6c10fa796ca0 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -61,6 +61,7 @@ #include #include #include +#include #include diff --git a/mm/readahead.c b/mm/readahead.c index 39bf45d43320..be20c9d699d3 100644 --- a/mm/readahead.c +++ b/mm/readahead.c @@ -15,6 +15,7 @@ #include #include #include +#include void default_unplug_io_fn(struct backing_dev_info *bdi, struct page *page) { From d24517d793f21edab1a411da95f2c45cb88a84aa Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 27 Sep 2007 12:46:11 +0200 Subject: [PATCH 11/37] Remove flush_dry_bio_endio The entire function of flush_dry_bio_endio is to undo the effects of bio_endio (when called on a barrier request). So remove the function and the call to bio_endio. This allows us to remove "bi_size" from "struct request_queue". Signed-off-by: Neil Brown ### Diffstat output ./block/ll_rw_blk.c | 39 ++------------------------------------- ./include/linux/blkdev.h | 1 - 2 files changed, 2 insertions(+), 38 deletions(-) diff .prev/block/ll_rw_blk.c ./block/ll_rw_blk.c Signed-off-by: Jens Axboe --- block/ll_rw_blk.c | 39 ++------------------------------------- include/linux/blkdev.h | 1 - 2 files changed, 2 insertions(+), 38 deletions(-) diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 3b2eff4e83a6..dfe0948ec8b2 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -431,7 +431,6 @@ static void queue_flush(struct request_queue *q, unsigned which) static inline struct request *start_ordered(struct request_queue *q, struct request *rq) { - q->bi_size = 0; q->orderr = 0; q->ordered = q->next_ordered; q->ordseq |= QUEUE_ORDSEQ_STARTED; @@ -528,55 +527,21 @@ int blk_do_ordered(struct request_queue *q, struct request **rqp) return 1; } -static int flush_dry_bio_endio(struct bio *bio, unsigned int bytes, int error) -{ - struct request_queue *q = bio->bi_private; - - /* - * This is dry run, restore bio_sector and size. We'll finish - * this request again with the original bi_end_io after an - * error occurs or post flush is complete. - */ - q->bi_size += bytes; - - if (bio->bi_size) - return 1; - - /* Reset bio */ - set_bit(BIO_UPTODATE, &bio->bi_flags); - bio->bi_size = q->bi_size; - bio->bi_sector -= (q->bi_size >> 9); - q->bi_size = 0; - - return 0; -} - static int ordered_bio_endio(struct request *rq, struct bio *bio, unsigned int nbytes, int error) { struct request_queue *q = rq->q; - bio_end_io_t *endio; - void *private; if (&q->bar_rq != rq) return 0; /* - * Okay, this is the barrier request in progress, dry finish it. + * Okay, this is the barrier request in progress, just + * record the error; */ if (error && !q->orderr) q->orderr = error; - endio = bio->bi_end_io; - private = bio->bi_private; - bio->bi_end_io = flush_dry_bio_endio; - bio->bi_private = q; - - bio_endio(bio, nbytes, error); - - bio->bi_end_io = endio; - bio->bi_private = private; - return 1; } diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index a0a998140447..95be0ac57e76 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -471,7 +471,6 @@ struct request_queue int orderr, ordcolor; struct request pre_flush_rq, bar_rq, post_flush_rq; struct request *orig_bar_rq; - unsigned int bi_size; struct mutex sysfs_lock; From 9cc54d40b8ca01fcefc9151044b6996565061d90 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 27 Sep 2007 12:46:12 +0200 Subject: [PATCH 12/37] Only call bi_end_io once for any bio Currently bi_end_io can be called multiple times as sub-requests complete. However no ->bi_end_io function wants to know about that. So only call when the bio is complete. Signed-off-by: Neil Brown ### Diffstat output ./fs/bio.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff .prev/fs/bio.c ./fs/bio.c Signed-off-by: Jens Axboe --- fs/bio.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/bio.c b/fs/bio.c index 29a44c1b64c6..5720b940bb5f 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -1018,6 +1018,8 @@ void bio_endio(struct bio *bio, unsigned int bytes_done, int error) { if (error) clear_bit(BIO_UPTODATE, &bio->bi_flags); + else if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) + error = -EIO; if (unlikely(bytes_done > bio->bi_size)) { printk("%s: want %u bytes done, only %u left\n", __FUNCTION__, @@ -1028,7 +1030,7 @@ void bio_endio(struct bio *bio, unsigned int bytes_done, int error) bio->bi_size -= bytes_done; bio->bi_sector += (bytes_done >> 9); - if (bio->bi_end_io) + if (bio->bi_size && bio->bi_end_io) bio->bi_end_io(bio, bytes_done, error); } From 5bb23a688b2de23d7765a1dd439d89c038378978 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 27 Sep 2007 12:46:13 +0200 Subject: [PATCH 13/37] Don't decrement bi_size in bio_endio The only caller of bio_endio that does not pass the full bi_size is end_that_request_first. Also, no ->bi_end_io method is really interested in bi_size being decremented. So move the decrement and related code into ll_rw_blk and merge it with order_bio_endio to form req_bio_endio which does endio functionality specific to request completion. As some ->bi_end_io methods do check bi_size of 0, we set it thus for now, but that will go in the next patch. Signed-off-by: Neil Brown ### Diffstat output ./block/ll_rw_blk.c | 42 +++++++++++++++++++++++++++--------------- ./fs/bio.c | 23 +++++++++++------------ 2 files changed, 38 insertions(+), 27 deletions(-) diff .prev/block/ll_rw_blk.c ./block/ll_rw_blk.c Signed-off-by: Jens Axboe --- block/ll_rw_blk.c | 42 +++++++++++++++++++++++++++--------------- fs/bio.c | 23 +++++++++++------------ 2 files changed, 38 insertions(+), 27 deletions(-) diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index dfe0948ec8b2..b55ed0df33f0 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -527,22 +527,36 @@ int blk_do_ordered(struct request_queue *q, struct request **rqp) return 1; } -static int ordered_bio_endio(struct request *rq, struct bio *bio, - unsigned int nbytes, int error) +static void req_bio_endio(struct request *rq, struct bio *bio, + unsigned int nbytes, int error) { struct request_queue *q = rq->q; - if (&q->bar_rq != rq) - return 0; + if (&q->bar_rq != rq) { + if (error) + clear_bit(BIO_UPTODATE, &bio->bi_flags); + else if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) + error = -EIO; - /* - * Okay, this is the barrier request in progress, just - * record the error; - */ - if (error && !q->orderr) - q->orderr = error; + if (unlikely(nbytes > bio->bi_size)) { + printk("%s: want %u bytes done, only %u left\n", + __FUNCTION__, nbytes, bio->bi_size); + nbytes = bio->bi_size; + } - return 1; + bio->bi_size -= nbytes; + bio->bi_sector += (nbytes >> 9); + if (bio->bi_size == 0) + bio_endio(bio, bio->bi_size, error); + } else { + + /* + * Okay, this is the barrier request in progress, just + * record the error; + */ + if (error && !q->orderr) + q->orderr = error; + } } /** @@ -3388,8 +3402,7 @@ static int __end_that_request_first(struct request *req, int uptodate, if (nr_bytes >= bio->bi_size) { req->bio = bio->bi_next; nbytes = bio->bi_size; - if (!ordered_bio_endio(req, bio, nbytes, error)) - bio_endio(bio, nbytes, error); + req_bio_endio(req, bio, nbytes, error); next_idx = 0; bio_nbytes = 0; } else { @@ -3444,8 +3457,7 @@ static int __end_that_request_first(struct request *req, int uptodate, * if the request wasn't completed, update state */ if (bio_nbytes) { - if (!ordered_bio_endio(req, bio, bio_nbytes, error)) - bio_endio(bio, bio_nbytes, error); + req_bio_endio(req, bio, bio_nbytes, error); bio->bi_idx += next_idx; bio_iovec(bio)->bv_offset += nr_bytes; bio_iovec(bio)->bv_len -= nr_bytes; diff --git a/fs/bio.c b/fs/bio.c index 5720b940bb5f..3adecd64ff6e 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -1006,13 +1006,14 @@ void bio_check_pages_dirty(struct bio *bio) * @error: error, if any * * Description: - * bio_endio() will end I/O on @bytes_done number of bytes. This may be - * just a partial part of the bio, or it may be the whole bio. bio_endio() - * is the preferred way to end I/O on a bio, it takes care of decrementing - * bi_size and clearing BIO_UPTODATE on error. @error is 0 on success, and - * and one of the established -Exxxx (-EIO, for instance) error values in - * case something went wrong. Noone should call bi_end_io() directly on - * a bio unless they own it and thus know that it has an end_io function. + * bio_endio() will end I/O on @bytes_done number of bytes. This + * must always be the whole (remaining) bio. bio_endio() is the + * preferred way to end I/O on a bio, it takes care of clearing + * BIO_UPTODATE on error. @error is 0 on success, and and one of the + * established -Exxxx (-EIO, for instance) error values in case + * something went wrong. Noone should call bi_end_io() directly on a + * bio unless they own it and thus know that it has an end_io + * function. **/ void bio_endio(struct bio *bio, unsigned int bytes_done, int error) { @@ -1021,16 +1022,14 @@ void bio_endio(struct bio *bio, unsigned int bytes_done, int error) else if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) error = -EIO; - if (unlikely(bytes_done > bio->bi_size)) { + if (unlikely(bytes_done != bio->bi_size)) { printk("%s: want %u bytes done, only %u left\n", __FUNCTION__, bytes_done, bio->bi_size); bytes_done = bio->bi_size; } - bio->bi_size -= bytes_done; - bio->bi_sector += (bytes_done >> 9); - - if (bio->bi_size && bio->bi_end_io) + bio->bi_size = 0; /* expected by some callees - will be removed */ + if (bio->bi_end_io) bio->bi_end_io(bio, bytes_done, error); } From 6712ecf8f648118c3363c142196418f89a510b90 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 27 Sep 2007 12:47:43 +0200 Subject: [PATCH 14/37] Drop 'size' argument from bio_endio and bi_end_io As bi_end_io is only called once when the reqeust is complete, the 'size' argument is now redundant. Remove it. Now there is no need for bio_endio to subtract the size completed from bi_size. So don't do that either. While we are at it, change bi_end_io to return void. Signed-off-by: Neil Brown Signed-off-by: Jens Axboe --- block/ll_rw_blk.c | 10 ++++---- drivers/block/aoe/aoeblk.c | 4 +-- drivers/block/aoe/aoecmd.c | 2 +- drivers/block/aoe/aoedev.c | 4 +-- drivers/block/cciss.c | 2 +- drivers/block/cpqarray.c | 2 +- drivers/block/floppy.c | 6 +---- drivers/block/loop.c | 4 +-- drivers/block/pktcdvd.c | 25 +++++-------------- drivers/block/rd.c | 4 +-- drivers/block/umem.c | 2 +- drivers/md/dm-crypt.c | 21 ++++++---------- drivers/md/dm-emc.c | 5 +--- drivers/md/dm-io.c | 8 +----- drivers/md/dm-mpath.c | 4 +-- drivers/md/dm-raid1.c | 4 +-- drivers/md/dm-snap.c | 2 +- drivers/md/dm-zero.c | 2 +- drivers/md/dm.c | 18 ++++++-------- drivers/md/faulty.c | 10 +++----- drivers/md/linear.c | 4 +-- drivers/md/md.c | 25 ++++++------------- drivers/md/multipath.c | 13 +++------- drivers/md/raid0.c | 4 +-- drivers/md/raid1.c | 30 ++++++---------------- drivers/md/raid10.c | 31 ++++++----------------- drivers/md/raid5.c | 48 ++++++++++++------------------------ drivers/s390/block/dcssblk.c | 4 +-- drivers/s390/block/xpram.c | 6 ++--- drivers/scsi/scsi_lib.c | 10 +++----- fs/bio.c | 35 ++++++-------------------- fs/block_dev.c | 2 +- fs/buffer.c | 6 +---- fs/direct-io.c | 13 ++-------- fs/gfs2/super.c | 4 +-- fs/jfs/jfs_logmgr.c | 5 +--- fs/jfs/jfs_metapage.c | 12 ++------- fs/mpage.c | 12 ++------- fs/ocfs2/cluster/heartbeat.c | 4 --- fs/xfs/linux-2.6/xfs_aops.c | 4 --- fs/xfs/linux-2.6/xfs_buf.c | 4 --- include/linux/bio.h | 6 ++--- include/linux/swap.h | 2 +- mm/bounce.c | 25 ++++--------------- mm/page_io.c | 12 ++------- 45 files changed, 132 insertions(+), 328 deletions(-) diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index b55ed0df33f0..cd9d2c5d91ae 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -547,7 +547,7 @@ static void req_bio_endio(struct request *rq, struct bio *bio, bio->bi_size -= nbytes; bio->bi_sector += (nbytes >> 9); if (bio->bi_size == 0) - bio_endio(bio, bio->bi_size, error); + bio_endio(bio, error); } else { /* @@ -2401,7 +2401,7 @@ static int __blk_rq_map_user(struct request_queue *q, struct request *rq, return bio->bi_size; /* if it was boucned we must call the end io function */ - bio_endio(bio, bio->bi_size, 0); + bio_endio(bio, 0); __blk_rq_unmap_user(orig_bio); bio_put(bio); return ret; @@ -2510,7 +2510,7 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq, return PTR_ERR(bio); if (bio->bi_size != len) { - bio_endio(bio, bio->bi_size, 0); + bio_endio(bio, 0); bio_unmap_user(bio); return -EINVAL; } @@ -3040,7 +3040,7 @@ out: return 0; end_io: - bio_endio(bio, nr_sectors << 9, err); + bio_endio(bio, err); return 0; } @@ -3187,7 +3187,7 @@ static inline void __generic_make_request(struct bio *bio) bdevname(bio->bi_bdev, b), (long long) bio->bi_sector); end_io: - bio_endio(bio, bio->bi_size, -EIO); + bio_endio(bio, -EIO); break; } diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index 007faaf008e7..b1d00ef6659c 100644 --- a/drivers/block/aoe/aoeblk.c +++ b/drivers/block/aoe/aoeblk.c @@ -138,7 +138,7 @@ aoeblk_make_request(struct request_queue *q, struct bio *bio) buf = mempool_alloc(d->bufpool, GFP_NOIO); if (buf == NULL) { printk(KERN_INFO "aoe: buf allocation failure\n"); - bio_endio(bio, bio->bi_size, -ENOMEM); + bio_endio(bio, -ENOMEM); return 0; } memset(buf, 0, sizeof(*buf)); @@ -159,7 +159,7 @@ aoeblk_make_request(struct request_queue *q, struct bio *bio) d->aoemajor, d->aoeminor); spin_unlock_irqrestore(&d->lock, flags); mempool_free(buf, d->bufpool); - bio_endio(bio, bio->bi_size, -ENXIO); + bio_endio(bio, -ENXIO); return 0; } diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 01fbdd38e3be..5abae34ad65b 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -652,7 +652,7 @@ aoecmd_ata_rsp(struct sk_buff *skb) disk_stat_add(disk, sectors[rw], n_sect); disk_stat_add(disk, io_ticks, duration); n = (buf->flags & BUFFL_FAIL) ? -EIO : 0; - bio_endio(buf->bio, buf->bio->bi_size, n); + bio_endio(buf->bio, n); mempool_free(buf, d->bufpool); } } diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c index 05a97197c918..51f50710e5fc 100644 --- a/drivers/block/aoe/aoedev.c +++ b/drivers/block/aoe/aoedev.c @@ -119,7 +119,7 @@ aoedev_downdev(struct aoedev *d) bio = buf->bio; if (--buf->nframesout == 0) { mempool_free(buf, d->bufpool); - bio_endio(bio, bio->bi_size, -EIO); + bio_endio(bio, -EIO); } skb_shinfo(f->skb)->nr_frags = f->skb->data_len = 0; } @@ -130,7 +130,7 @@ aoedev_downdev(struct aoedev *d) list_del(d->bufq.next); bio = buf->bio; mempool_free(buf, d->bufpool); - bio_endio(bio, bio->bi_size, -EIO); + bio_endio(bio, -EIO); } if (d->gd) diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 084358a828e9..28d145756f6c 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -1194,7 +1194,7 @@ static inline void complete_buffers(struct bio *bio, int status) int nr_sectors = bio_sectors(bio); bio->bi_next = NULL; - bio_endio(bio, nr_sectors << 9, status ? 0 : -EIO); + bio_endio(bio, status ? 0 : -EIO); bio = xbh; } } diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c index eb9799acf65b..3853c9a38d6a 100644 --- a/drivers/block/cpqarray.c +++ b/drivers/block/cpqarray.c @@ -987,7 +987,7 @@ static inline void complete_buffers(struct bio *bio, int ok) xbh = bio->bi_next; bio->bi_next = NULL; - bio_endio(bio, nr_sectors << 9, ok ? 0 : -EIO); + bio_endio(bio, ok ? 0 : -EIO); bio = xbh; } diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index f0a86e201b44..80483aac4cc9 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -3810,14 +3810,10 @@ static int check_floppy_change(struct gendisk *disk) * a disk in the drive, and whether that disk is writable. */ -static int floppy_rb0_complete(struct bio *bio, unsigned int bytes_done, +static void floppy_rb0_complete(struct bio *bio, int err) { - if (bio->bi_size) - return 1; - complete((struct completion *)bio->bi_private); - return 0; } static int __floppy_read_block_0(struct block_device *bdev) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 9f015fce4135..b9233a06934c 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -551,7 +551,7 @@ static int loop_make_request(struct request_queue *q, struct bio *old_bio) out: spin_unlock_irq(&lo->lo_lock); - bio_io_error(old_bio, old_bio->bi_size); + bio_io_error(old_bio); return 0; } @@ -580,7 +580,7 @@ static inline void loop_handle_bio(struct loop_device *lo, struct bio *bio) bio_put(bio); } else { int ret = do_bio_filebacked(lo, bio); - bio_endio(bio, bio->bi_size, ret); + bio_endio(bio, ret); } } diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index fadbfd880bab..540bf3676985 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -1058,15 +1058,12 @@ static void pkt_make_local_copy(struct packet_data *pkt, struct bio_vec *bvec) } } -static int pkt_end_io_read(struct bio *bio, unsigned int bytes_done, int err) +static void pkt_end_io_read(struct bio *bio, int err) { struct packet_data *pkt = bio->bi_private; struct pktcdvd_device *pd = pkt->pd; BUG_ON(!pd); - if (bio->bi_size) - return 1; - VPRINTK("pkt_end_io_read: bio=%p sec0=%llx sec=%llx err=%d\n", bio, (unsigned long long)pkt->sector, (unsigned long long)bio->bi_sector, err); @@ -1077,19 +1074,14 @@ static int pkt_end_io_read(struct bio *bio, unsigned int bytes_done, int err) wake_up(&pd->wqueue); } pkt_bio_finished(pd); - - return 0; } -static int pkt_end_io_packet_write(struct bio *bio, unsigned int bytes_done, int err) +static void pkt_end_io_packet_write(struct bio *bio, int err) { struct packet_data *pkt = bio->bi_private; struct pktcdvd_device *pd = pkt->pd; BUG_ON(!pd); - if (bio->bi_size) - return 1; - VPRINTK("pkt_end_io_packet_write: id=%d, err=%d\n", pkt->id, err); pd->stats.pkt_ended++; @@ -1098,7 +1090,6 @@ static int pkt_end_io_packet_write(struct bio *bio, unsigned int bytes_done, int atomic_dec(&pkt->io_wait); atomic_inc(&pkt->run_sm); wake_up(&pd->wqueue); - return 0; } /* @@ -1470,7 +1461,7 @@ static void pkt_finish_packet(struct packet_data *pkt, int uptodate) while (bio) { next = bio->bi_next; bio->bi_next = NULL; - bio_endio(bio, bio->bi_size, uptodate ? 0 : -EIO); + bio_endio(bio, uptodate ? 0 : -EIO); bio = next; } pkt->orig_bios = pkt->orig_bios_tail = NULL; @@ -2462,19 +2453,15 @@ static int pkt_close(struct inode *inode, struct file *file) } -static int pkt_end_io_read_cloned(struct bio *bio, unsigned int bytes_done, int err) +static void pkt_end_io_read_cloned(struct bio *bio, int err) { struct packet_stacked_data *psd = bio->bi_private; struct pktcdvd_device *pd = psd->pd; - if (bio->bi_size) - return 1; - bio_put(bio); - bio_endio(psd->bio, psd->bio->bi_size, err); + bio_endio(psd->bio, err); mempool_free(psd, psd_pool); pkt_bio_finished(pd); - return 0; } static int pkt_make_request(struct request_queue *q, struct bio *bio) @@ -2620,7 +2607,7 @@ static int pkt_make_request(struct request_queue *q, struct bio *bio) } return 0; end_io: - bio_io_error(bio, bio->bi_size); + bio_io_error(bio); return 0; } diff --git a/drivers/block/rd.c b/drivers/block/rd.c index 65150b548f3a..701ea77f62e9 100644 --- a/drivers/block/rd.c +++ b/drivers/block/rd.c @@ -287,10 +287,10 @@ static int rd_make_request(struct request_queue *q, struct bio *bio) if (ret) goto fail; - bio_endio(bio, bio->bi_size, 0); + bio_endio(bio, 0); return 0; fail: - bio_io_error(bio, bio->bi_size); + bio_io_error(bio); return 0; } diff --git a/drivers/block/umem.c b/drivers/block/umem.c index c378e285d708..be7fac86725e 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c @@ -545,7 +545,7 @@ static void process_page(unsigned long data) return_bio = bio->bi_next; bio->bi_next = NULL; - bio_endio(bio, bio->bi_size, 0); + bio_endio(bio, 0); } } diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index bdc52d6922b7..8216a6f75be5 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -489,7 +489,7 @@ static void dec_pending(struct dm_crypt_io *io, int error) if (!atomic_dec_and_test(&io->pending)) return; - bio_endio(io->base_bio, io->base_bio->bi_size, io->error); + bio_endio(io->base_bio, io->error); mempool_free(io, cc->io_pool); } @@ -509,25 +509,19 @@ static void kcryptd_queue_io(struct dm_crypt_io *io) queue_work(_kcryptd_workqueue, &io->work); } -static int crypt_endio(struct bio *clone, unsigned int done, int error) +static void crypt_endio(struct bio *clone, int error) { struct dm_crypt_io *io = clone->bi_private; struct crypt_config *cc = io->target->private; unsigned read_io = bio_data_dir(clone) == READ; /* - * free the processed pages, even if - * it's only a partially completed write + * free the processed pages */ - if (!read_io) - crypt_free_buffer_pages(cc, clone, done); - - /* keep going - not finished yet */ - if (unlikely(clone->bi_size)) - return 1; - - if (!read_io) + if (!read_io) { + crypt_free_buffer_pages(cc, clone, clone->bi_size); goto out; + } if (unlikely(!bio_flagged(clone, BIO_UPTODATE))) { error = -EIO; @@ -537,12 +531,11 @@ static int crypt_endio(struct bio *clone, unsigned int done, int error) bio_put(clone); io->post_process = 1; kcryptd_queue_io(io); - return 0; + return; out: bio_put(clone); dec_pending(io, error); - return error; } static void clone_init(struct dm_crypt_io *io, struct bio *clone) diff --git a/drivers/md/dm-emc.c b/drivers/md/dm-emc.c index 71cc858b7860..a2191a4fcf77 100644 --- a/drivers/md/dm-emc.c +++ b/drivers/md/dm-emc.c @@ -38,13 +38,10 @@ static inline void free_bio(struct bio *bio) bio_put(bio); } -static int emc_endio(struct bio *bio, unsigned int bytes_done, int error) +static void emc_endio(struct bio *bio, int error) { struct dm_path *path = bio->bi_private; - if (bio->bi_size) - return 1; - /* We also need to look at the sense keys here whether or not to * switch to the next PG etc. * diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c index f3a772486437..b8e342fe7586 100644 --- a/drivers/md/dm-io.c +++ b/drivers/md/dm-io.c @@ -124,15 +124,11 @@ static void dec_count(struct io *io, unsigned int region, int error) } } -static int endio(struct bio *bio, unsigned int done, int error) +static void endio(struct bio *bio, int error) { struct io *io; unsigned region; - /* keep going until we've finished */ - if (bio->bi_size) - return 1; - if (error && bio_data_dir(bio) == READ) zero_fill_bio(bio); @@ -146,8 +142,6 @@ static int endio(struct bio *bio, unsigned int done, int error) bio_put(bio); dec_count(io, region, error); - - return 0; } /*----------------------------------------------------------------- diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index d6ca9d0a6fd1..31056abca89d 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c @@ -390,11 +390,11 @@ static void dispatch_queued_ios(struct multipath *m) r = map_io(m, bio, mpio, 1); if (r < 0) - bio_endio(bio, bio->bi_size, r); + bio_endio(bio, r); else if (r == DM_MAPIO_REMAPPED) generic_make_request(bio); else if (r == DM_MAPIO_REQUEUE) - bio_endio(bio, bio->bi_size, -EIO); + bio_endio(bio, -EIO); bio = next; } diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index 144071e70a93..d09ff15490a5 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c @@ -820,7 +820,7 @@ static void write_callback(unsigned long error, void *context) break; } } - bio_endio(bio, bio->bi_size, 0); + bio_endio(bio, 0); } static void do_write(struct mirror_set *ms, struct bio *bio) @@ -900,7 +900,7 @@ static void do_writes(struct mirror_set *ms, struct bio_list *writes) */ if (unlikely(ms->log_failure)) while ((bio = bio_list_pop(&sync))) - bio_endio(bio, bio->bi_size, -EIO); + bio_endio(bio, -EIO); else while ((bio = bio_list_pop(&sync))) do_write(ms, bio); diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index 83ddbfe6b8a4..98a633f3d6b0 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c @@ -636,7 +636,7 @@ static void error_bios(struct bio *bio) while (bio) { n = bio->bi_next; bio->bi_next = NULL; - bio_io_error(bio, bio->bi_size); + bio_io_error(bio); bio = n; } } diff --git a/drivers/md/dm-zero.c b/drivers/md/dm-zero.c index f314d7dc9c26..bdec206c404b 100644 --- a/drivers/md/dm-zero.c +++ b/drivers/md/dm-zero.c @@ -43,7 +43,7 @@ static int zero_map(struct dm_target *ti, struct bio *bio, break; } - bio_endio(bio, bio->bi_size, 0); + bio_endio(bio, 0); /* accepted bio, don't make new request */ return DM_MAPIO_SUBMITTED; diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 2120155929a6..167765c47747 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -484,23 +484,20 @@ static void dec_pending(struct dm_io *io, int error) blk_add_trace_bio(io->md->queue, io->bio, BLK_TA_COMPLETE); - bio_endio(io->bio, io->bio->bi_size, io->error); + bio_endio(io->bio, io->error); } free_io(io->md, io); } } -static int clone_endio(struct bio *bio, unsigned int done, int error) +static void clone_endio(struct bio *bio, int error) { int r = 0; struct dm_target_io *tio = bio->bi_private; struct mapped_device *md = tio->io->md; dm_endio_fn endio = tio->ti->type->end_io; - if (bio->bi_size) - return 1; - if (!bio_flagged(bio, BIO_UPTODATE) && !error) error = -EIO; @@ -514,7 +511,7 @@ static int clone_endio(struct bio *bio, unsigned int done, int error) error = r; else if (r == DM_ENDIO_INCOMPLETE) /* The target will handle the io */ - return 1; + return; else if (r) { DMWARN("unimplemented target endio return value: %d", r); BUG(); @@ -530,7 +527,6 @@ static int clone_endio(struct bio *bio, unsigned int done, int error) bio_put(bio); free_tio(md, tio); - return r; } static sector_t max_io_len(struct mapped_device *md, @@ -761,7 +757,7 @@ static void __split_bio(struct mapped_device *md, struct bio *bio) ci.map = dm_get_table(md); if (!ci.map) { - bio_io_error(bio, bio->bi_size); + bio_io_error(bio); return; } @@ -803,7 +799,7 @@ static int dm_request(struct request_queue *q, struct bio *bio) * guarantee it is (or can be) handled by the targets correctly. */ if (unlikely(bio_barrier(bio))) { - bio_endio(bio, bio->bi_size, -EOPNOTSUPP); + bio_endio(bio, -EOPNOTSUPP); return 0; } @@ -820,13 +816,13 @@ static int dm_request(struct request_queue *q, struct bio *bio) up_read(&md->io_lock); if (bio_rw(bio) == READA) { - bio_io_error(bio, bio->bi_size); + bio_io_error(bio); return 0; } r = queue_io(md, bio); if (r < 0) { - bio_io_error(bio, bio->bi_size); + bio_io_error(bio); return 0; } else if (r == 0) diff --git a/drivers/md/faulty.c b/drivers/md/faulty.c index cb059cf14c2e..cf2ddce34118 100644 --- a/drivers/md/faulty.c +++ b/drivers/md/faulty.c @@ -65,18 +65,16 @@ #include -static int faulty_fail(struct bio *bio, unsigned int bytes_done, int error) +static void faulty_fail(struct bio *bio, int error) { struct bio *b = bio->bi_private; b->bi_size = bio->bi_size; b->bi_sector = bio->bi_sector; - if (bio->bi_size == 0) - bio_put(bio); + bio_put(bio); - clear_bit(BIO_UPTODATE, &b->bi_flags); - return (b->bi_end_io)(b, bytes_done, -EIO); + bio_io_error(b); } typedef struct faulty_conf { @@ -179,7 +177,7 @@ static int make_request(struct request_queue *q, struct bio *bio) /* special case - don't decrement, don't generic_make_request, * just fail immediately */ - bio_endio(bio, bio->bi_size, -EIO); + bio_endio(bio, -EIO); return 0; } diff --git a/drivers/md/linear.c b/drivers/md/linear.c index 17f795c3e0ab..550148770bb2 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c @@ -338,7 +338,7 @@ static int linear_make_request (struct request_queue *q, struct bio *bio) sector_t block; if (unlikely(bio_barrier(bio))) { - bio_endio(bio, bio->bi_size, -EOPNOTSUPP); + bio_endio(bio, -EOPNOTSUPP); return 0; } @@ -358,7 +358,7 @@ static int linear_make_request (struct request_queue *q, struct bio *bio) bdevname(tmp_dev->rdev->bdev, b), (unsigned long long)tmp_dev->size, (unsigned long long)tmp_dev->offset); - bio_io_error(bio, bio->bi_size); + bio_io_error(bio); return 0; } if (unlikely(bio->bi_sector + (bio->bi_size >> 9) > diff --git a/drivers/md/md.c b/drivers/md/md.c index f883b7e37f3d..e8f102ea9b03 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -213,7 +213,7 @@ static DEFINE_SPINLOCK(all_mddevs_lock); static int md_fail_request (struct request_queue *q, struct bio *bio) { - bio_io_error(bio, bio->bi_size); + bio_io_error(bio); return 0; } @@ -384,12 +384,10 @@ static void free_disk_sb(mdk_rdev_t * rdev) } -static int super_written(struct bio *bio, unsigned int bytes_done, int error) +static void super_written(struct bio *bio, int error) { mdk_rdev_t *rdev = bio->bi_private; mddev_t *mddev = rdev->mddev; - if (bio->bi_size) - return 1; if (error || !test_bit(BIO_UPTODATE, &bio->bi_flags)) { printk("md: super_written gets error=%d, uptodate=%d\n", @@ -401,16 +399,13 @@ static int super_written(struct bio *bio, unsigned int bytes_done, int error) if (atomic_dec_and_test(&mddev->pending_writes)) wake_up(&mddev->sb_wait); bio_put(bio); - return 0; } -static int super_written_barrier(struct bio *bio, unsigned int bytes_done, int error) +static void super_written_barrier(struct bio *bio, int error) { struct bio *bio2 = bio->bi_private; mdk_rdev_t *rdev = bio2->bi_private; mddev_t *mddev = rdev->mddev; - if (bio->bi_size) - return 1; if (!test_bit(BIO_UPTODATE, &bio->bi_flags) && error == -EOPNOTSUPP) { @@ -424,11 +419,11 @@ static int super_written_barrier(struct bio *bio, unsigned int bytes_done, int e spin_unlock_irqrestore(&mddev->write_lock, flags); wake_up(&mddev->sb_wait); bio_put(bio); - return 0; + } else { + bio_put(bio2); + bio->bi_private = rdev; + super_written(bio, error); } - bio_put(bio2); - bio->bi_private = rdev; - return super_written(bio, bytes_done, error); } void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev, @@ -489,13 +484,9 @@ void md_super_wait(mddev_t *mddev) finish_wait(&mddev->sb_wait, &wq); } -static int bi_complete(struct bio *bio, unsigned int bytes_done, int error) +static void bi_complete(struct bio *bio, int error) { - if (bio->bi_size) - return 1; - complete((struct completion*)bio->bi_private); - return 0; } int sync_page_io(struct block_device *bdev, sector_t sector, int size, diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index 1e2af43a73b9..f2a63f394ad9 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c @@ -82,21 +82,17 @@ static void multipath_end_bh_io (struct multipath_bh *mp_bh, int err) struct bio *bio = mp_bh->master_bio; multipath_conf_t *conf = mddev_to_conf(mp_bh->mddev); - bio_endio(bio, bio->bi_size, err); + bio_endio(bio, err); mempool_free(mp_bh, conf->pool); } -static int multipath_end_request(struct bio *bio, unsigned int bytes_done, - int error) +static void multipath_end_request(struct bio *bio, int error) { int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); struct multipath_bh * mp_bh = (struct multipath_bh *)(bio->bi_private); multipath_conf_t *conf = mddev_to_conf(mp_bh->mddev); mdk_rdev_t *rdev = conf->multipaths[mp_bh->path].rdev; - if (bio->bi_size) - return 1; - if (uptodate) multipath_end_bh_io(mp_bh, 0); else if (!bio_rw_ahead(bio)) { @@ -112,7 +108,6 @@ static int multipath_end_request(struct bio *bio, unsigned int bytes_done, } else multipath_end_bh_io(mp_bh, error); rdev_dec_pending(rdev, conf->mddev); - return 0; } static void unplug_slaves(mddev_t *mddev) @@ -155,7 +150,7 @@ static int multipath_make_request (struct request_queue *q, struct bio * bio) const int rw = bio_data_dir(bio); if (unlikely(bio_barrier(bio))) { - bio_endio(bio, bio->bi_size, -EOPNOTSUPP); + bio_endio(bio, -EOPNOTSUPP); return 0; } @@ -169,7 +164,7 @@ static int multipath_make_request (struct request_queue *q, struct bio * bio) mp_bh->path = multipath_map(conf); if (mp_bh->path < 0) { - bio_endio(bio, bio->bi_size, -EIO); + bio_endio(bio, -EIO); mempool_free(mp_bh, conf->pool); return 0; } diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index b8216bc6db45..ef0da2d84959 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -420,7 +420,7 @@ static int raid0_make_request (struct request_queue *q, struct bio *bio) const int rw = bio_data_dir(bio); if (unlikely(bio_barrier(bio))) { - bio_endio(bio, bio->bi_size, -EOPNOTSUPP); + bio_endio(bio, -EOPNOTSUPP); return 0; } @@ -490,7 +490,7 @@ bad_map: " or bigger than %dk %llu %d\n", chunk_size, (unsigned long long)bio->bi_sector, bio->bi_size >> 10); - bio_io_error(bio, bio->bi_size); + bio_io_error(bio); return 0; } diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index f33a729960ca..6d03bea6fa58 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -238,7 +238,7 @@ static void raid_end_bio_io(r1bio_t *r1_bio) (unsigned long long) bio->bi_sector + (bio->bi_size >> 9) - 1); - bio_endio(bio, bio->bi_size, + bio_endio(bio, test_bit(R1BIO_Uptodate, &r1_bio->state) ? 0 : -EIO); } free_r1bio(r1_bio); @@ -255,16 +255,13 @@ static inline void update_head_pos(int disk, r1bio_t *r1_bio) r1_bio->sector + (r1_bio->sectors); } -static int raid1_end_read_request(struct bio *bio, unsigned int bytes_done, int error) +static void raid1_end_read_request(struct bio *bio, int error) { int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private); int mirror; conf_t *conf = mddev_to_conf(r1_bio->mddev); - if (bio->bi_size) - return 1; - mirror = r1_bio->read_disk; /* * this branch is our 'one mirror IO has finished' event handler: @@ -301,10 +298,9 @@ static int raid1_end_read_request(struct bio *bio, unsigned int bytes_done, int } rdev_dec_pending(conf->mirrors[mirror].rdev, conf->mddev); - return 0; } -static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int error) +static void raid1_end_write_request(struct bio *bio, int error) { int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private); @@ -312,8 +308,6 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int conf_t *conf = mddev_to_conf(r1_bio->mddev); struct bio *to_put = NULL; - if (bio->bi_size) - return 1; for (mirror = 0; mirror < conf->raid_disks; mirror++) if (r1_bio->bios[mirror] == bio) @@ -366,7 +360,7 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int (unsigned long long) mbio->bi_sector, (unsigned long long) mbio->bi_sector + (mbio->bi_size >> 9) - 1); - bio_endio(mbio, mbio->bi_size, 0); + bio_endio(mbio, 0); } } } @@ -400,8 +394,6 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int if (to_put) bio_put(to_put); - - return 0; } @@ -796,7 +788,7 @@ static int make_request(struct request_queue *q, struct bio * bio) if (unlikely(!mddev->barriers_work && bio_barrier(bio))) { if (rw == WRITE) md_write_end(mddev); - bio_endio(bio, bio->bi_size, -EOPNOTSUPP); + bio_endio(bio, -EOPNOTSUPP); return 0; } @@ -1137,14 +1129,11 @@ abort: } -static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error) +static void end_sync_read(struct bio *bio, int error) { r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private); int i; - if (bio->bi_size) - return 1; - for (i=r1_bio->mddev->raid_disks; i--; ) if (r1_bio->bios[i] == bio) break; @@ -1160,10 +1149,9 @@ static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error) if (atomic_dec_and_test(&r1_bio->remaining)) reschedule_retry(r1_bio); - return 0; } -static int end_sync_write(struct bio *bio, unsigned int bytes_done, int error) +static void end_sync_write(struct bio *bio, int error) { int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private); @@ -1172,9 +1160,6 @@ static int end_sync_write(struct bio *bio, unsigned int bytes_done, int error) int i; int mirror=0; - if (bio->bi_size) - return 1; - for (i = 0; i < conf->raid_disks; i++) if (r1_bio->bios[i] == bio) { mirror = i; @@ -1200,7 +1185,6 @@ static int end_sync_write(struct bio *bio, unsigned int bytes_done, int error) md_done_sync(mddev, r1_bio->sectors, uptodate); put_buf(r1_bio); } - return 0; } static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio) diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 4e53792aa520..25a96c42bdb0 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -227,7 +227,7 @@ static void raid_end_bio_io(r10bio_t *r10_bio) { struct bio *bio = r10_bio->master_bio; - bio_endio(bio, bio->bi_size, + bio_endio(bio, test_bit(R10BIO_Uptodate, &r10_bio->state) ? 0 : -EIO); free_r10bio(r10_bio); } @@ -243,15 +243,13 @@ static inline void update_head_pos(int slot, r10bio_t *r10_bio) r10_bio->devs[slot].addr + (r10_bio->sectors); } -static int raid10_end_read_request(struct bio *bio, unsigned int bytes_done, int error) +static void raid10_end_read_request(struct bio *bio, int error) { int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); r10bio_t * r10_bio = (r10bio_t *)(bio->bi_private); int slot, dev; conf_t *conf = mddev_to_conf(r10_bio->mddev); - if (bio->bi_size) - return 1; slot = r10_bio->read_slot; dev = r10_bio->devs[slot].devnum; @@ -284,19 +282,15 @@ static int raid10_end_read_request(struct bio *bio, unsigned int bytes_done, int } rdev_dec_pending(conf->mirrors[dev].rdev, conf->mddev); - return 0; } -static int raid10_end_write_request(struct bio *bio, unsigned int bytes_done, int error) +static void raid10_end_write_request(struct bio *bio, int error) { int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); r10bio_t * r10_bio = (r10bio_t *)(bio->bi_private); int slot, dev; conf_t *conf = mddev_to_conf(r10_bio->mddev); - if (bio->bi_size) - return 1; - for (slot = 0; slot < conf->copies; slot++) if (r10_bio->devs[slot].bio == bio) break; @@ -339,7 +333,6 @@ static int raid10_end_write_request(struct bio *bio, unsigned int bytes_done, in } rdev_dec_pending(conf->mirrors[dev].rdev, conf->mddev); - return 0; } @@ -787,7 +780,7 @@ static int make_request(struct request_queue *q, struct bio * bio) unsigned long flags; if (unlikely(bio_barrier(bio))) { - bio_endio(bio, bio->bi_size, -EOPNOTSUPP); + bio_endio(bio, -EOPNOTSUPP); return 0; } @@ -819,7 +812,7 @@ static int make_request(struct request_queue *q, struct bio * bio) " or bigger than %dk %llu %d\n", chunk_sects/2, (unsigned long long)bio->bi_sector, bio->bi_size >> 10); - bio_io_error(bio, bio->bi_size); + bio_io_error(bio); return 0; } @@ -1155,15 +1148,12 @@ abort: } -static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error) +static void end_sync_read(struct bio *bio, int error) { r10bio_t * r10_bio = (r10bio_t *)(bio->bi_private); conf_t *conf = mddev_to_conf(r10_bio->mddev); int i,d; - if (bio->bi_size) - return 1; - for (i=0; icopies; i++) if (r10_bio->devs[i].bio == bio) break; @@ -1192,10 +1182,9 @@ static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error) reschedule_retry(r10_bio); } rdev_dec_pending(conf->mirrors[d].rdev, conf->mddev); - return 0; } -static int end_sync_write(struct bio *bio, unsigned int bytes_done, int error) +static void end_sync_write(struct bio *bio, int error) { int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); r10bio_t * r10_bio = (r10bio_t *)(bio->bi_private); @@ -1203,9 +1192,6 @@ static int end_sync_write(struct bio *bio, unsigned int bytes_done, int error) conf_t *conf = mddev_to_conf(mddev); int i,d; - if (bio->bi_size) - return 1; - for (i = 0; i < conf->copies; i++) if (r10_bio->devs[i].bio == bio) break; @@ -1228,7 +1214,6 @@ static int end_sync_write(struct bio *bio, unsigned int bytes_done, int error) } } rdev_dec_pending(conf->mirrors[d].rdev, mddev); - return 0; } /* @@ -1374,7 +1359,7 @@ static void recovery_request_write(mddev_t *mddev, r10bio_t *r10_bio) if (test_bit(R10BIO_Uptodate, &r10_bio->state)) generic_make_request(wbio); else - bio_endio(wbio, wbio->bi_size, -EIO); + bio_endio(wbio, -EIO); } diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index f96dea975fa5..caaca9e178bc 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -108,12 +108,11 @@ static void return_io(struct bio *return_bi) { struct bio *bi = return_bi; while (bi) { - int bytes = bi->bi_size; return_bi = bi->bi_next; bi->bi_next = NULL; bi->bi_size = 0; - bi->bi_end_io(bi, bytes, + bi->bi_end_io(bi, test_bit(BIO_UPTODATE, &bi->bi_flags) ? 0 : -EIO); bi = return_bi; @@ -382,10 +381,10 @@ static unsigned long get_stripe_work(struct stripe_head *sh) return pending; } -static int -raid5_end_read_request(struct bio *bi, unsigned int bytes_done, int error); -static int -raid5_end_write_request (struct bio *bi, unsigned int bytes_done, int error); +static void +raid5_end_read_request(struct bio *bi, int error); +static void +raid5_end_write_request(struct bio *bi, int error); static void ops_run_io(struct stripe_head *sh) { @@ -1110,8 +1109,7 @@ static void shrink_stripes(raid5_conf_t *conf) conf->slab_cache = NULL; } -static int raid5_end_read_request(struct bio * bi, unsigned int bytes_done, - int error) +static void raid5_end_read_request(struct bio * bi, int error) { struct stripe_head *sh = bi->bi_private; raid5_conf_t *conf = sh->raid_conf; @@ -1120,8 +1118,6 @@ static int raid5_end_read_request(struct bio * bi, unsigned int bytes_done, char b[BDEVNAME_SIZE]; mdk_rdev_t *rdev; - if (bi->bi_size) - return 1; for (i=0 ; idev[i].req) @@ -1132,7 +1128,7 @@ static int raid5_end_read_request(struct bio * bi, unsigned int bytes_done, uptodate); if (i == disks) { BUG(); - return 0; + return; } if (uptodate) { @@ -1185,20 +1181,15 @@ static int raid5_end_read_request(struct bio * bi, unsigned int bytes_done, clear_bit(R5_LOCKED, &sh->dev[i].flags); set_bit(STRIPE_HANDLE, &sh->state); release_stripe(sh); - return 0; } -static int raid5_end_write_request (struct bio *bi, unsigned int bytes_done, - int error) +static void raid5_end_write_request (struct bio *bi, int error) { struct stripe_head *sh = bi->bi_private; raid5_conf_t *conf = sh->raid_conf; int disks = sh->disks, i; int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags); - if (bi->bi_size) - return 1; - for (i=0 ; idev[i].req) break; @@ -1208,7 +1199,7 @@ static int raid5_end_write_request (struct bio *bi, unsigned int bytes_done, uptodate); if (i == disks) { BUG(); - return 0; + return; } if (!uptodate) @@ -1219,7 +1210,6 @@ static int raid5_end_write_request (struct bio *bi, unsigned int bytes_done, clear_bit(R5_LOCKED, &sh->dev[i].flags); set_bit(STRIPE_HANDLE, &sh->state); release_stripe(sh); - return 0; } @@ -3340,7 +3330,7 @@ static struct bio *remove_bio_from_retry(raid5_conf_t *conf) * first). * If the read failed.. */ -static int raid5_align_endio(struct bio *bi, unsigned int bytes, int error) +static void raid5_align_endio(struct bio *bi, int error) { struct bio* raid_bi = bi->bi_private; mddev_t *mddev; @@ -3348,8 +3338,6 @@ static int raid5_align_endio(struct bio *bi, unsigned int bytes, int error) int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags); mdk_rdev_t *rdev; - if (bi->bi_size) - return 1; bio_put(bi); mddev = raid_bi->bi_bdev->bd_disk->queue->queuedata; @@ -3360,17 +3348,16 @@ static int raid5_align_endio(struct bio *bi, unsigned int bytes, int error) rdev_dec_pending(rdev, conf->mddev); if (!error && uptodate) { - bio_endio(raid_bi, bytes, 0); + bio_endio(raid_bi, 0); if (atomic_dec_and_test(&conf->active_aligned_reads)) wake_up(&conf->wait_for_stripe); - return 0; + return; } pr_debug("raid5_align_endio : io error...handing IO for a retry\n"); add_bio_to_retry(raid_bi, conf); - return 0; } static int bio_fits_rdev(struct bio *bi) @@ -3476,7 +3463,7 @@ static int make_request(struct request_queue *q, struct bio * bi) int remaining; if (unlikely(bio_barrier(bi))) { - bio_endio(bi, bi->bi_size, -EOPNOTSUPP); + bio_endio(bi, -EOPNOTSUPP); return 0; } @@ -3592,12 +3579,11 @@ static int make_request(struct request_queue *q, struct bio * bi) remaining = --bi->bi_phys_segments; spin_unlock_irq(&conf->device_lock); if (remaining == 0) { - int bytes = bi->bi_size; if ( rw == WRITE ) md_write_end(mddev); - bi->bi_size = 0; - bi->bi_end_io(bi, bytes, + + bi->bi_end_io(bi, test_bit(BIO_UPTODATE, &bi->bi_flags) ? 0 : -EIO); } @@ -3875,10 +3861,8 @@ static int retry_aligned_read(raid5_conf_t *conf, struct bio *raid_bio) remaining = --raid_bio->bi_phys_segments; spin_unlock_irq(&conf->device_lock); if (remaining == 0) { - int bytes = raid_bio->bi_size; - raid_bio->bi_size = 0; - raid_bio->bi_end_io(raid_bio, bytes, + raid_bio->bi_end_io(raid_bio, test_bit(BIO_UPTODATE, &raid_bio->bi_flags) ? 0 : -EIO); } diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index 4d8798bacf97..859f870552e3 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c @@ -674,10 +674,10 @@ dcssblk_make_request(struct request_queue *q, struct bio *bio) } bytes_done += bvec->bv_len; } - bio_endio(bio, bytes_done, 0); + bio_endio(bio, 0); return 0; fail: - bio_io_error(bio, bio->bi_size); + bio_io_error(bio); return 0; } diff --git a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c index 354a060e5bec..0fbacc8b1063 100644 --- a/drivers/s390/block/xpram.c +++ b/drivers/s390/block/xpram.c @@ -230,12 +230,10 @@ static int xpram_make_request(struct request_queue *q, struct bio *bio) } } set_bit(BIO_UPTODATE, &bio->bi_flags); - bytes = bio->bi_size; - bio->bi_size = 0; - bio->bi_end_io(bio, bytes, 0); + bio_end_io(bio, 0); return 0; fail: - bio_io_error(bio, bio->bi_size); + bio_io_error(bio); return 0; } diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 59b398530295..604f4d717933 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -266,13 +266,9 @@ static int scsi_merge_bio(struct request *rq, struct bio *bio) return blk_rq_append_bio(q, rq, bio); } -static int scsi_bi_endio(struct bio *bio, unsigned int bytes_done, int error) +static void scsi_bi_endio(struct bio *bio, int error) { - if (bio->bi_size) - return 1; - bio_put(bio); - return 0; } /** @@ -328,7 +324,7 @@ static int scsi_req_map_sg(struct request *rq, struct scatterlist *sgl, if (bio->bi_vcnt >= nr_vecs) { err = scsi_merge_bio(rq, bio); if (err) { - bio_endio(bio, bio->bi_size, 0); + bio_endio(bio, 0); goto free_bios; } bio = NULL; @@ -350,7 +346,7 @@ free_bios: /* * call endio instead of bio_put incase it was bounced */ - bio_endio(bio, bio->bi_size, 0); + bio_endio(bio, 0); } return err; diff --git a/fs/bio.c b/fs/bio.c index 3adecd64ff6e..5f604f269dfa 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -798,13 +798,9 @@ void bio_unmap_user(struct bio *bio) bio_put(bio); } -static int bio_map_kern_endio(struct bio *bio, unsigned int bytes_done, int err) +static void bio_map_kern_endio(struct bio *bio, int err) { - if (bio->bi_size) - return 1; - bio_put(bio); - return 0; } @@ -1002,12 +998,10 @@ void bio_check_pages_dirty(struct bio *bio) /** * bio_endio - end I/O on a bio * @bio: bio - * @bytes_done: number of bytes completed * @error: error, if any * * Description: - * bio_endio() will end I/O on @bytes_done number of bytes. This - * must always be the whole (remaining) bio. bio_endio() is the + * bio_endio() will end I/O on the whole bio. bio_endio() is the * preferred way to end I/O on a bio, it takes care of clearing * BIO_UPTODATE on error. @error is 0 on success, and and one of the * established -Exxxx (-EIO, for instance) error values in case @@ -1015,22 +1009,15 @@ void bio_check_pages_dirty(struct bio *bio) * bio unless they own it and thus know that it has an end_io * function. **/ -void bio_endio(struct bio *bio, unsigned int bytes_done, int error) +void bio_endio(struct bio *bio, int error) { if (error) clear_bit(BIO_UPTODATE, &bio->bi_flags); else if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) error = -EIO; - if (unlikely(bytes_done != bio->bi_size)) { - printk("%s: want %u bytes done, only %u left\n", __FUNCTION__, - bytes_done, bio->bi_size); - bytes_done = bio->bi_size; - } - - bio->bi_size = 0; /* expected by some callees - will be removed */ if (bio->bi_end_io) - bio->bi_end_io(bio, bytes_done, error); + bio->bi_end_io(bio, error); } void bio_pair_release(struct bio_pair *bp) @@ -1038,37 +1025,29 @@ void bio_pair_release(struct bio_pair *bp) if (atomic_dec_and_test(&bp->cnt)) { struct bio *master = bp->bio1.bi_private; - bio_endio(master, master->bi_size, bp->error); + bio_endio(master, bp->error); mempool_free(bp, bp->bio2.bi_private); } } -static int bio_pair_end_1(struct bio * bi, unsigned int done, int err) +static void bio_pair_end_1(struct bio *bi, int err) { struct bio_pair *bp = container_of(bi, struct bio_pair, bio1); if (err) bp->error = err; - if (bi->bi_size) - return 1; - bio_pair_release(bp); - return 0; } -static int bio_pair_end_2(struct bio * bi, unsigned int done, int err) +static void bio_pair_end_2(struct bio *bi, int err) { struct bio_pair *bp = container_of(bi, struct bio_pair, bio2); if (err) bp->error = err; - if (bi->bi_size) - return 1; - bio_pair_release(bp); - return 0; } /* diff --git a/fs/block_dev.c b/fs/block_dev.c index 2980eabe5779..6339a30879b7 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -172,7 +172,7 @@ blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, } #if 0 -static int blk_end_aio(struct bio *bio, unsigned int bytes_done, int error) +static void blk_end_aio(struct bio *bio, int error) { struct kiocb *iocb = bio->bi_private; atomic_t *bio_count = &iocb->ki_bio_count; diff --git a/fs/buffer.c b/fs/buffer.c index 0e5ec371ce72..75b51dfa5e03 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -2634,13 +2634,10 @@ sector_t generic_block_bmap(struct address_space *mapping, sector_t block, return tmp.b_blocknr; } -static int end_bio_bh_io_sync(struct bio *bio, unsigned int bytes_done, int err) +static void end_bio_bh_io_sync(struct bio *bio, int err) { struct buffer_head *bh = bio->bi_private; - if (bio->bi_size) - return 1; - if (err == -EOPNOTSUPP) { set_bit(BIO_EOPNOTSUPP, &bio->bi_flags); set_bit(BH_Eopnotsupp, &bh->b_state); @@ -2648,7 +2645,6 @@ static int end_bio_bh_io_sync(struct bio *bio, unsigned int bytes_done, int err) bh->b_end_io(bh, test_bit(BIO_UPTODATE, &bio->bi_flags)); bio_put(bio); - return 0; } int submit_bh(int rw, struct buffer_head * bh) diff --git a/fs/direct-io.c b/fs/direct-io.c index 901dc55e9f54..b5928a7b6a5a 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c @@ -264,15 +264,12 @@ static int dio_bio_complete(struct dio *dio, struct bio *bio); /* * Asynchronous IO callback. */ -static int dio_bio_end_aio(struct bio *bio, unsigned int bytes_done, int error) +static void dio_bio_end_aio(struct bio *bio, int error) { struct dio *dio = bio->bi_private; unsigned long remaining; unsigned long flags; - if (bio->bi_size) - return 1; - /* cleanup the bio */ dio_bio_complete(dio, bio); @@ -287,8 +284,6 @@ static int dio_bio_end_aio(struct bio *bio, unsigned int bytes_done, int error) aio_complete(dio->iocb, ret, 0); kfree(dio); } - - return 0; } /* @@ -298,21 +293,17 @@ static int dio_bio_end_aio(struct bio *bio, unsigned int bytes_done, int error) * During I/O bi_private points at the dio. After I/O, bi_private is used to * implement a singly-linked list of completed BIOs, at dio->bio_list. */ -static int dio_bio_end_io(struct bio *bio, unsigned int bytes_done, int error) +static void dio_bio_end_io(struct bio *bio, int error) { struct dio *dio = bio->bi_private; unsigned long flags; - if (bio->bi_size) - return 1; - spin_lock_irqsave(&dio->bio_lock, flags); bio->bi_private = dio->bio_list; dio->bio_list = bio; if (--dio->refcount == 1 && dio->waiter) wake_up_process(dio->waiter); spin_unlock_irqrestore(&dio->bio_lock, flags); - return 0; } static int diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index f916b9740c75..2473e2a86d1b 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -160,11 +160,9 @@ int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb_host *sb, int silent) } -static int end_bio_io_page(struct bio *bio, unsigned int bytes_done, int error) +static void end_bio_io_page(struct bio *bio, int error) { struct page *page = bio->bi_private; - if (bio->bi_size) - return 1; if (!error) SetPageUptodate(page); diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c index de3e4a506dbc..57c3b8ac36bf 100644 --- a/fs/jfs/jfs_logmgr.c +++ b/fs/jfs/jfs_logmgr.c @@ -2200,16 +2200,13 @@ static int lbmIOWait(struct lbuf * bp, int flag) * * executed at INTIODONE level */ -static int lbmIODone(struct bio *bio, unsigned int bytes_done, int error) +static void lbmIODone(struct bio *bio, int error) { struct lbuf *bp = bio->bi_private; struct lbuf *nextbp, *tail; struct jfs_log *log; unsigned long flags; - if (bio->bi_size) - return 1; - /* * get back jfs buffer bound to the i/o buffer */ diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c index 62e96be02acf..1332adc0b9fa 100644 --- a/fs/jfs/jfs_metapage.c +++ b/fs/jfs/jfs_metapage.c @@ -280,14 +280,10 @@ static void last_read_complete(struct page *page) unlock_page(page); } -static int metapage_read_end_io(struct bio *bio, unsigned int bytes_done, - int err) +static void metapage_read_end_io(struct bio *bio, int err) { struct page *page = bio->bi_private; - if (bio->bi_size) - return 1; - if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) { printk(KERN_ERR "metapage_read_end_io: I/O error\n"); SetPageError(page); @@ -341,16 +337,12 @@ static void last_write_complete(struct page *page) end_page_writeback(page); } -static int metapage_write_end_io(struct bio *bio, unsigned int bytes_done, - int err) +static void metapage_write_end_io(struct bio *bio, int err) { struct page *page = bio->bi_private; BUG_ON(!PagePrivate(page)); - if (bio->bi_size) - return 1; - if (! test_bit(BIO_UPTODATE, &bio->bi_flags)) { printk(KERN_ERR "metapage_write_end_io: I/O error\n"); SetPageError(page); diff --git a/fs/mpage.c b/fs/mpage.c index c1698f2291aa..b1c3e5890508 100644 --- a/fs/mpage.c +++ b/fs/mpage.c @@ -39,14 +39,11 @@ * status of that page is hard. See end_buffer_async_read() for the details. * There is no point in duplicating all that complexity. */ -static int mpage_end_io_read(struct bio *bio, unsigned int bytes_done, int err) +static void mpage_end_io_read(struct bio *bio, int err) { const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; - if (bio->bi_size) - return 1; - do { struct page *page = bvec->bv_page; @@ -62,17 +59,13 @@ static int mpage_end_io_read(struct bio *bio, unsigned int bytes_done, int err) unlock_page(page); } while (bvec >= bio->bi_io_vec); bio_put(bio); - return 0; } -static int mpage_end_io_write(struct bio *bio, unsigned int bytes_done, int err) +static void mpage_end_io_write(struct bio *bio, int err) { const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; - if (bio->bi_size) - return 1; - do { struct page *page = bvec->bv_page; @@ -87,7 +80,6 @@ static int mpage_end_io_write(struct bio *bio, unsigned int bytes_done, int err) end_page_writeback(page); } while (bvec >= bio->bi_io_vec); bio_put(bio); - return 0; } static struct bio *mpage_bio_submit(int rw, struct bio *bio) diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c index 2bd7f788cf34..da2c2b442b49 100644 --- a/fs/ocfs2/cluster/heartbeat.c +++ b/fs/ocfs2/cluster/heartbeat.c @@ -217,7 +217,6 @@ static void o2hb_wait_on_io(struct o2hb_region *reg, } static int o2hb_bio_end_io(struct bio *bio, - unsigned int bytes_done, int error) { struct o2hb_bio_wait_ctxt *wc = bio->bi_private; @@ -227,9 +226,6 @@ static int o2hb_bio_end_io(struct bio *bio, wc->wc_error = error; } - if (bio->bi_size) - return 1; - o2hb_bio_wait_dec(wc, 1); bio_put(bio); return 0; diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index 5f152f60d74d..3f13519436af 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c @@ -326,14 +326,10 @@ xfs_iomap_valid( STATIC int xfs_end_bio( struct bio *bio, - unsigned int bytes_done, int error) { xfs_ioend_t *ioend = bio->bi_private; - if (bio->bi_size) - return 1; - ASSERT(atomic_read(&bio->bi_cnt) >= 1); ioend->io_error = test_bit(BIO_UPTODATE, &bio->bi_flags) ? 0 : error; diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index b0f0e58866de..6a75f4d984a1 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c @@ -1106,16 +1106,12 @@ _xfs_buf_ioend( STATIC int xfs_buf_bio_end_io( struct bio *bio, - unsigned int bytes_done, int error) { xfs_buf_t *bp = (xfs_buf_t *)bio->bi_private; unsigned int blocksize = bp->b_target->bt_bsize; struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; - if (bio->bi_size) - return 1; - if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) bp->b_error = EIO; diff --git a/include/linux/bio.h b/include/linux/bio.h index 1ddef34f43c3..089a8bc55dd4 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -64,7 +64,7 @@ struct bio_vec { struct bio_set; struct bio; -typedef int (bio_end_io_t) (struct bio *, unsigned int, int); +typedef void (bio_end_io_t) (struct bio *, int); typedef void (bio_destructor_t) (struct bio *); /* @@ -226,7 +226,7 @@ struct bio { #define BIO_SEG_BOUNDARY(q, b1, b2) \ BIOVEC_SEG_BOUNDARY((q), __BVEC_END((b1)), __BVEC_START((b2))) -#define bio_io_error(bio, bytes) bio_endio((bio), (bytes), -EIO) +#define bio_io_error(bio) bio_endio((bio), -EIO) /* * drivers should not use the __ version unless they _really_ want to @@ -286,7 +286,7 @@ extern struct bio *bio_alloc_bioset(gfp_t, int, struct bio_set *); extern void bio_put(struct bio *); extern void bio_free(struct bio *, struct bio_set *); -extern void bio_endio(struct bio *, unsigned int, int); +extern void bio_endio(struct bio *, int); struct request_queue; extern int bio_phys_segments(struct request_queue *, struct bio *); extern int bio_hw_segments(struct request_queue *, struct bio *); diff --git a/include/linux/swap.h b/include/linux/swap.h index 665f85f2a3af..edf681a7fd8f 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -221,7 +221,7 @@ extern void swap_unplug_io_fn(struct backing_dev_info *, struct page *); /* linux/mm/page_io.c */ extern int swap_readpage(struct file *, struct page *); extern int swap_writepage(struct page *page, struct writeback_control *wbc); -extern int end_swap_bio_read(struct bio *bio, unsigned int bytes_done, int err); +extern void end_swap_bio_read(struct bio *bio, int err); /* linux/mm/swap_state.c */ extern struct address_space swapper_space; diff --git a/mm/bounce.c b/mm/bounce.c index 179fe38a2416..3b549bf31f7d 100644 --- a/mm/bounce.c +++ b/mm/bounce.c @@ -140,26 +140,19 @@ static void bounce_end_io(struct bio *bio, mempool_t *pool, int err) mempool_free(bvec->bv_page, pool); } - bio_endio(bio_orig, bio_orig->bi_size, err); + bio_endio(bio_orig, err); bio_put(bio); } -static int bounce_end_io_write(struct bio *bio, unsigned int bytes_done, int err) +static void bounce_end_io_write(struct bio *bio, int err) { - if (bio->bi_size) - return 1; - bounce_end_io(bio, page_pool, err); - return 0; } -static int bounce_end_io_write_isa(struct bio *bio, unsigned int bytes_done, int err) +static void bounce_end_io_write_isa(struct bio *bio, int err) { - if (bio->bi_size) - return 1; bounce_end_io(bio, isa_page_pool, err); - return 0; } static void __bounce_end_io_read(struct bio *bio, mempool_t *pool, int err) @@ -172,22 +165,14 @@ static void __bounce_end_io_read(struct bio *bio, mempool_t *pool, int err) bounce_end_io(bio, pool, err); } -static int bounce_end_io_read(struct bio *bio, unsigned int bytes_done, int err) +static void bounce_end_io_read(struct bio *bio, int err) { - if (bio->bi_size) - return 1; - __bounce_end_io_read(bio, page_pool, err); - return 0; } -static int bounce_end_io_read_isa(struct bio *bio, unsigned int bytes_done, int err) +static void bounce_end_io_read_isa(struct bio *bio, int err) { - if (bio->bi_size) - return 1; - __bounce_end_io_read(bio, isa_page_pool, err); - return 0; } static void __blk_queue_bounce(struct request_queue *q, struct bio **bio_orig, diff --git a/mm/page_io.c b/mm/page_io.c index dbffec0d78c9..3b97f6850273 100644 --- a/mm/page_io.c +++ b/mm/page_io.c @@ -44,14 +44,11 @@ static struct bio *get_swap_bio(gfp_t gfp_flags, pgoff_t index, return bio; } -static int end_swap_bio_write(struct bio *bio, unsigned int bytes_done, int err) +static void end_swap_bio_write(struct bio *bio, int err) { const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); struct page *page = bio->bi_io_vec[0].bv_page; - if (bio->bi_size) - return 1; - if (!uptodate) { SetPageError(page); /* @@ -71,17 +68,13 @@ static int end_swap_bio_write(struct bio *bio, unsigned int bytes_done, int err) } end_page_writeback(page); bio_put(bio); - return 0; } -int end_swap_bio_read(struct bio *bio, unsigned int bytes_done, int err) +void end_swap_bio_read(struct bio *bio, int err) { const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); struct page *page = bio->bi_io_vec[0].bv_page; - if (bio->bi_size) - return 1; - if (!uptodate) { SetPageError(page); ClearPageUptodate(page); @@ -94,7 +87,6 @@ int end_swap_bio_read(struct bio *bio, unsigned int bytes_done, int err) } unlock_page(page); bio_put(bio); - return 0; } /* From c9d3d8ecf672c513435691a886876aee5ab11001 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 1 Oct 2007 16:33:51 +0200 Subject: [PATCH 15/37] Add Xilinx SystemACE entry to maintainers I'm the author of the SystemACE driver Signed-off-by: Grant Likely Signed-off-by: Jens Axboe --- MAINTAINERS | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 9a91d9e3f1f2..53144f4737ff 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4176,6 +4176,13 @@ W: http://oss.sgi.com/projects/xfs T: git git://oss.sgi.com:8090/xfs/xfs-2.6.git S: Supported +XILINX SYSTEMACE DRIVER +P: Grant Likely +M: grant.likely@secretlab.ca +W: http://www.secretlab.ca/ +L: linux-kernel@vger.kernel.org +S: Maintained + XILINX UARTLITE SERIAL DRIVER P: Peter Korsgaard M: jacmet@sunsite.dk From edec49616c7b4ad7ceb3b936a8d95b10652ee677 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 1 Oct 2007 16:33:52 +0200 Subject: [PATCH 16/37] Sysace: Use the established platform bus api SystemACE uses the platform bus binding, but it doesn't use the platform bus API. Move to using the correct API for consistency sake and future proofing against platform bus changes. Signed-off-by: Grant Likely Signed-off-by: Jens Axboe --- drivers/block/xsysace.c | 48 +++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index 3ede0b63da13..b10447611afd 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c @@ -1060,13 +1060,12 @@ static void __devexit ace_teardown(struct ace_device *ace) * Platform Bus Support */ -static int __devinit ace_probe(struct device *device) +static int __devinit ace_probe(struct platform_device *dev) { - struct platform_device *dev = to_platform_device(device); struct ace_device *ace; int i; - dev_dbg(device, "ace_probe(%p)\n", device); + dev_dbg(&dev->dev, "ace_probe(%p)\n", dev); /* * Allocate the ace device structure @@ -1075,7 +1074,7 @@ static int __devinit ace_probe(struct device *device) if (!ace) goto err_alloc; - ace->dev = device; + ace->dev = &dev->dev; ace->id = dev->id; ace->irq = NO_IRQ; @@ -1089,7 +1088,7 @@ static int __devinit ace_probe(struct device *device) /* FIXME: Should get bus_width from the platform_device struct */ ace->bus_width = 1; - dev_set_drvdata(&dev->dev, ace); + platform_set_drvdata(dev, ace); /* Call the bus-independant setup code */ if (ace_setup(ace) != 0) @@ -1098,7 +1097,7 @@ static int __devinit ace_probe(struct device *device) return 0; err_setup: - dev_set_drvdata(&dev->dev, NULL); + platform_set_drvdata(dev, NULL); kfree(ace); err_alloc: printk(KERN_ERR "xsysace: could not initialize device\n"); @@ -1108,25 +1107,27 @@ static int __devinit ace_probe(struct device *device) /* * Platform bus remove() method */ -static int __devexit ace_remove(struct device *device) +static int __devexit ace_remove(struct platform_device *dev) { - struct ace_device *ace = dev_get_drvdata(device); - - dev_dbg(device, "ace_remove(%p)\n", device); + struct ace_device *ace = platform_get_drvdata(dev); + dev_dbg(&dev->dev, "ace_remove(%p)\n", dev); if (ace) { ace_teardown(ace); + platform_set_drvdata(dev, NULL); kfree(ace); } return 0; } -static struct device_driver ace_driver = { - .name = "xsysace", - .bus = &platform_bus_type, +static struct platform_driver ace_platform_driver = { .probe = ace_probe, .remove = __devexit_p(ace_remove), + .driver = { + .owner = THIS_MODULE, + .name = "xsysace", + }, }; /* --------------------------------------------------------------------- @@ -1134,20 +1135,31 @@ static struct device_driver ace_driver = { */ static int __init ace_init(void) { + int rc; + ace_major = register_blkdev(ace_major, "xsysace"); if (ace_major <= 0) { - printk(KERN_WARNING "xsysace: register_blkdev() failed\n"); - return ace_major; + rc = -ENOMEM; + goto err_blk; } - pr_debug("Registering Xilinx SystemACE driver, major=%i\n", ace_major); - return driver_register(&ace_driver); + if ((rc = platform_driver_register(&ace_platform_driver)) != 0) + goto err_plat; + + pr_info("Xilinx SystemACE device driver, major=%i\n", ace_major); + return 0; + + err_plat: + unregister_blkdev(ace_major, "xsysace"); + err_blk: + printk(KERN_ERR "xsysace: registration failed; err=%i\n", rc); + return rc; } static void __exit ace_exit(void) { pr_debug("Unregistering Xilinx SystemACE driver\n"); - driver_unregister(&ace_driver); + platform_driver_unregister(&ace_platform_driver); unregister_blkdev(ace_major, "xsysace"); } From 1b455466549f46bab0a75a7a296a9331a38fd6fa Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 1 Oct 2007 16:33:53 +0200 Subject: [PATCH 17/37] Sysace: Move structure allocation from bus binding into common code Split the determination of device registers/irqs/etc from the actual allocation and initialization of the device structure. This cleans up the code a bit in preparation to add an of_platform bus binding Signed-off-by: Grant Likely Signed-off-by: Jens Axboe --- drivers/block/xsysace.c | 103 ++++++++++++++++++++++++---------------- 1 file changed, 63 insertions(+), 40 deletions(-) diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index b10447611afd..555939bd2d53 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c @@ -1033,7 +1033,7 @@ static int __devinit ace_setup(struct ace_device *ace) if (ace->irq != NO_IRQ) free_irq(ace->irq, ace); err_ioremap: - printk(KERN_INFO "xsysace: error initializing device at 0x%lx\n", + dev_info(ace->dev, "xsysace: error initializing device at 0x%lx\n", ace->physaddr); return -ENOMEM; } @@ -1056,52 +1056,83 @@ static void __devexit ace_teardown(struct ace_device *ace) iounmap(ace->baseaddr); } +static int __devinit +ace_alloc(struct device *dev, int id, unsigned long physaddr, + int irq, int bus_width) +{ + struct ace_device *ace; + int rc; + dev_dbg(dev, "ace_alloc(%p)\n", dev); + + if (!physaddr) { + rc = -ENODEV; + goto err_noreg; + } + + /* Allocate and initialize the ace device structure */ + ace = kzalloc(sizeof(struct ace_device), GFP_KERNEL); + if (!ace) { + rc = -ENOMEM; + goto err_alloc; + } + + ace->dev = dev; + ace->id = id; + ace->physaddr = physaddr; + ace->irq = irq; + ace->bus_width = bus_width; + + /* Call the setup code */ + if ((rc = ace_setup(ace)) != 0) + goto err_setup; + + dev_set_drvdata(dev, ace); + return 0; + + err_setup: + dev_set_drvdata(dev, NULL); + kfree(ace); + err_alloc: + err_noreg: + dev_err(dev, "could not initialize device, err=%i\n", rc); + return rc; +} + +static void __devexit ace_free(struct device *dev) +{ + struct ace_device *ace = dev_get_drvdata(dev); + dev_dbg(dev, "ace_free(%p)\n", dev); + + if (ace) { + ace_teardown(ace); + dev_set_drvdata(dev, NULL); + kfree(ace); + } +} + /* --------------------------------------------------------------------- * Platform Bus Support */ static int __devinit ace_probe(struct platform_device *dev) { - struct ace_device *ace; + unsigned long physaddr = 0; + int bus_width = 1; /* FIXME: should not be hard coded */ + int id = dev->id; + int irq = NO_IRQ; int i; dev_dbg(&dev->dev, "ace_probe(%p)\n", dev); - /* - * Allocate the ace device structure - */ - ace = kzalloc(sizeof(struct ace_device), GFP_KERNEL); - if (!ace) - goto err_alloc; - - ace->dev = &dev->dev; - ace->id = dev->id; - ace->irq = NO_IRQ; - for (i = 0; i < dev->num_resources; i++) { if (dev->resource[i].flags & IORESOURCE_MEM) - ace->physaddr = dev->resource[i].start; + physaddr = dev->resource[i].start; if (dev->resource[i].flags & IORESOURCE_IRQ) - ace->irq = dev->resource[i].start; + irq = dev->resource[i].start; } - /* FIXME: Should get bus_width from the platform_device struct */ - ace->bus_width = 1; - - platform_set_drvdata(dev, ace); - /* Call the bus-independant setup code */ - if (ace_setup(ace) != 0) - goto err_setup; - - return 0; - - err_setup: - platform_set_drvdata(dev, NULL); - kfree(ace); - err_alloc: - printk(KERN_ERR "xsysace: could not initialize device\n"); - return -ENOMEM; + return ace_alloc(&dev->dev, id, physaddr, irq, bus_width); } /* @@ -1109,15 +1140,7 @@ static int __devinit ace_probe(struct platform_device *dev) */ static int __devexit ace_remove(struct platform_device *dev) { - struct ace_device *ace = platform_get_drvdata(dev); - dev_dbg(&dev->dev, "ace_remove(%p)\n", dev); - - if (ace) { - ace_teardown(ace); - platform_set_drvdata(dev, NULL); - kfree(ace); - } - + ace_free(&dev->dev); return 0; } From 4a24d8610df542b6599a65b100d438df144574de Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 1 Oct 2007 16:33:54 +0200 Subject: [PATCH 18/37] Sysace: minor rework and cleanup changes Miscellanious rework to the sysace driver; Not critical, but makes the subsequent addition of the of_platform bus binding a wee bit cleaner Signed-off-by: Grant Likely Signed-off-by: Jens Axboe --- drivers/block/xsysace.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index 555939bd2d53..10bb4e54f685 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c @@ -158,6 +158,9 @@ MODULE_LICENSE("GPL"); #define ACE_FIFO_SIZE (32) #define ACE_BUF_PER_SECTOR (ACE_SECTOR_SIZE / ACE_FIFO_SIZE) +#define ACE_BUS_WIDTH_8 0 +#define ACE_BUS_WIDTH_16 1 + struct ace_reg_ops; struct ace_device { @@ -931,9 +934,11 @@ static int __devinit ace_setup(struct ace_device *ace) { u16 version; u16 val; - int rc; + dev_dbg(ace->dev, "ace_setup(ace=0x%p)\n", ace); + dev_dbg(ace->dev, "physaddr=0x%lx irq=%i\n", ace->physaddr, ace->irq); + spin_lock_init(&ace->lock); init_completion(&ace->id_completion); @@ -982,7 +987,7 @@ static int __devinit ace_setup(struct ace_device *ace) snprintf(ace->gd->disk_name, 32, "xs%c", ace->id + 'a'); /* set bus width */ - if (ace->bus_width == 1) { + if (ace->bus_width == ACE_BUS_WIDTH_16) { /* 0x0101 should work regardless of endianess */ ace_out_le16(ace, ACE_BUSMODE, 0x0101); @@ -1117,7 +1122,7 @@ static void __devexit ace_free(struct device *dev) static int __devinit ace_probe(struct platform_device *dev) { unsigned long physaddr = 0; - int bus_width = 1; /* FIXME: should not be hard coded */ + int bus_width = ACE_BUS_WIDTH_16; /* FIXME: should not be hard coded */ int id = dev->id; int irq = NO_IRQ; int i; @@ -1166,6 +1171,7 @@ static int __init ace_init(void) goto err_blk; } + pr_debug("xsysace: registering platform binding\n"); if ((rc = platform_driver_register(&ace_platform_driver)) != 0) goto err_plat; From 32f6fff47df65d25d3dedbd2953508c05225b726 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 1 Oct 2007 16:33:54 +0200 Subject: [PATCH 19/37] Sysace: Move IRQ handler registration to occur after FSM is initialized The FSM needs to be initialized before it is safe to call the ISR Signed-off-by: Grant Likely Signed-off-by: Jens Axboe --- drivers/block/xsysace.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index 10bb4e54f685..296d5674a3c1 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c @@ -949,15 +949,6 @@ static int __devinit ace_setup(struct ace_device *ace) if (!ace->baseaddr) goto err_ioremap; - if (ace->irq != NO_IRQ) { - rc = request_irq(ace->irq, ace_interrupt, 0, "systemace", ace); - if (rc) { - /* Failure - fall back to polled mode */ - dev_err(ace->dev, "request_irq failed\n"); - ace->irq = NO_IRQ; - } - } - /* * Initialize the state machine tasklet and stall timer */ @@ -1015,6 +1006,16 @@ static int __devinit ace_setup(struct ace_device *ace) val |= ACE_CTRL_DATABUFRDYIRQ | ACE_CTRL_ERRORIRQ; ace_out(ace, ACE_CTRL, val); + /* Now we can hook up the irq handler */ + if (ace->irq != NO_IRQ) { + rc = request_irq(ace->irq, ace_interrupt, 0, "systemace", ace); + if (rc) { + /* Failure - fall back to polled mode */ + dev_err(ace->dev, "request_irq failed\n"); + ace->irq = NO_IRQ; + } + } + /* Print the identification */ dev_info(ace->dev, "Xilinx SystemACE revision %i.%i.%i\n", (version >> 12) & 0xf, (version >> 8) & 0x0f, version & 0xff); @@ -1035,8 +1036,6 @@ static int __devinit ace_setup(struct ace_device *ace) blk_cleanup_queue(ace->queue); err_blk_initq: iounmap(ace->baseaddr); - if (ace->irq != NO_IRQ) - free_irq(ace->irq, ace); err_ioremap: dev_info(ace->dev, "xsysace: error initializing device at 0x%lx\n", ace->physaddr); From 95e896c35f3c3157159b89682b60281640b5d148 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 1 Oct 2007 16:33:55 +0200 Subject: [PATCH 20/37] Sysace: Add of_platform_bus binding The of_platform bus binding is needed to make the device driver usable under arch/powerpc. Signed-off-by: Grant Likely Signed-off-by: Jens Axboe --- drivers/block/xsysace.c | 89 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index 296d5674a3c1..56c4af3c2edb 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c @@ -91,6 +91,10 @@ #include #include #include +#if defined(CONFIG_OF) +#include +#include +#endif MODULE_AUTHOR("Grant Likely "); MODULE_DESCRIPTION("Xilinx SystemACE device driver"); @@ -1157,6 +1161,85 @@ static struct platform_driver ace_platform_driver = { }, }; +/* --------------------------------------------------------------------- + * OF_Platform Bus Support + */ + +#if defined(CONFIG_OF) +static int __devinit +ace_of_probe(struct of_device *op, const struct of_device_id *match) +{ + struct resource res; + unsigned long physaddr; + const u32 *id; + int irq, bus_width, rc; + + dev_dbg(&op->dev, "ace_of_probe(%p, %p)\n", op, match); + + /* device id */ + id = of_get_property(op->node, "port-number", NULL); + + /* physaddr */ + rc = of_address_to_resource(op->node, 0, &res); + if (rc) { + dev_err(&op->dev, "invalid address\n"); + return rc; + } + physaddr = res.start; + + /* irq */ + irq = irq_of_parse_and_map(op->node, 0); + + /* bus width */ + bus_width = ACE_BUS_WIDTH_16; + if (of_find_property(op->node, "8-bit", NULL)) + bus_width = ACE_BUS_WIDTH_8; + + /* Call the bus-independant setup code */ + return ace_alloc(&op->dev, id ? *id : 0, physaddr, irq, bus_width); +} + +static int __devexit ace_of_remove(struct of_device *op) +{ + ace_free(&op->dev); + return 0; +} + +/* Match table for of_platform binding */ +static struct of_device_id __devinit ace_of_match[] = { + { .compatible = "xilinx,xsysace", }, + {}, +}; +MODULE_DEVICE_TABLE(of, ace_of_match); + +static struct of_platform_driver ace_of_driver = { + .owner = THIS_MODULE, + .name = "xsysace", + .match_table = ace_of_match, + .probe = ace_of_probe, + .remove = __devexit_p(ace_of_remove), + .driver = { + .name = "xsysace", + }, +}; + +/* Registration helpers to keep the number of #ifdefs to a minimum */ +static inline int __init ace_of_register(void) +{ + pr_debug("xsysace: registering OF binding\n"); + return of_register_platform_driver(&ace_of_driver); +} + +static inline void __exit ace_of_unregister(void) +{ + of_unregister_platform_driver(&ace_of_driver); +} +#else /* CONFIG_OF */ +/* CONFIG_OF not enabled; do nothing helpers */ +static inline int __init ace_of_register(void) { return 0; } +static inline void __exit ace_of_unregister(void) { } +#endif /* CONFIG_OF */ + /* --------------------------------------------------------------------- * Module init/exit routines */ @@ -1170,6 +1253,9 @@ static int __init ace_init(void) goto err_blk; } + if ((rc = ace_of_register()) != 0) + goto err_of; + pr_debug("xsysace: registering platform binding\n"); if ((rc = platform_driver_register(&ace_platform_driver)) != 0) goto err_plat; @@ -1178,6 +1264,8 @@ static int __init ace_init(void) return 0; err_plat: + ace_of_unregister(); + err_of: unregister_blkdev(ace_major, "xsysace"); err_blk: printk(KERN_ERR "xsysace: registration failed; err=%i\n", rc); @@ -1188,6 +1276,7 @@ static void __exit ace_exit(void) { pr_debug("Unregistering Xilinx SystemACE driver\n"); platform_driver_unregister(&ace_platform_driver); + ace_of_unregister(); unregister_blkdev(ace_major, "xsysace"); } From ed155a95a4eb7d8dae61b64ab394314c5195e414 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 1 Oct 2007 16:33:56 +0200 Subject: [PATCH 21/37] Sysace: Labels in C code should not be indented. Remove the indentation on labels Signed-off-by: Grant Likely Signed-off-by: Jens Axboe --- drivers/block/xsysace.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index 56c4af3c2edb..3ea172b7b7a4 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c @@ -1034,13 +1034,13 @@ static int __devinit ace_setup(struct ace_device *ace) return 0; - err_read: +err_read: put_disk(ace->gd); - err_alloc_disk: +err_alloc_disk: blk_cleanup_queue(ace->queue); - err_blk_initq: +err_blk_initq: iounmap(ace->baseaddr); - err_ioremap: +err_ioremap: dev_info(ace->dev, "xsysace: error initializing device at 0x%lx\n", ace->physaddr); return -ENOMEM; @@ -1097,11 +1097,11 @@ ace_alloc(struct device *dev, int id, unsigned long physaddr, dev_set_drvdata(dev, ace); return 0; - err_setup: +err_setup: dev_set_drvdata(dev, NULL); kfree(ace); - err_alloc: - err_noreg: +err_alloc: +err_noreg: dev_err(dev, "could not initialize device, err=%i\n", rc); return rc; } @@ -1263,11 +1263,11 @@ static int __init ace_init(void) pr_info("Xilinx SystemACE device driver, major=%i\n", ace_major); return 0; - err_plat: +err_plat: ace_of_unregister(); - err_of: +err_of: unregister_blkdev(ace_major, "xsysace"); - err_blk: +err_blk: printk(KERN_ERR "xsysace: registration failed; err=%i\n", rc); return rc; } From 3084f0c6105a71e43225c36b4d97c1407988a242 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Thu, 27 Sep 2007 06:25:06 -0400 Subject: [PATCH 22/37] drivers/block/umem: move private include away from include/linux Move include/linux/umem.h to drivers/block, as umem.c is the only user, and its not an exported header. Move the PCI_{VENDOR,DEVICE}_ID_* constants to include/linux/pci_ids.h. Signed-off-by: Jeff Garzik --- drivers/block/umem.c | 2 +- {include/linux => drivers/block}/umem.h | 5 ----- include/linux/pci_ids.h | 5 +++++ 3 files changed, 6 insertions(+), 6 deletions(-) rename {include/linux => drivers/block}/umem.h (95%) diff --git a/drivers/block/umem.c b/drivers/block/umem.c index be7fac86725e..33ef7661e1c1 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c @@ -52,7 +52,7 @@ #include /* O_ACCMODE */ #include /* HDIO_GETGEO */ -#include +#include "umem.h" #include #include diff --git a/include/linux/umem.h b/drivers/block/umem.h similarity index 95% rename from include/linux/umem.h rename to drivers/block/umem.h index f36ebfc32bf6..3a3819afed92 100644 --- a/include/linux/umem.h +++ b/drivers/block/umem.h @@ -125,11 +125,6 @@ struct mm_dma_desc { __le64 sem_control_bits; } __attribute__((aligned(8))); -#define PCI_VENDOR_ID_MICRO_MEMORY 0x1332 -#define PCI_DEVICE_ID_MICRO_MEMORY_5415CN 0x5415 -#define PCI_DEVICE_ID_MICRO_MEMORY_5425CN 0x5425 -#define PCI_DEVICE_ID_MICRO_MEMORY_6155 0x6155 - /* bits for card->flags */ #define UM_FLAG_DMA_IN_REGS 1 #define UM_FLAG_NO_BYTE_STATUS 2 diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 55f307ffbf96..506b9ae241fd 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1736,6 +1736,11 @@ #define PCI_VENDOR_ID_RADISYS 0x1331 +#define PCI_VENDOR_ID_MICRO_MEMORY 0x1332 +#define PCI_DEVICE_ID_MICRO_MEMORY_5415CN 0x5415 +#define PCI_DEVICE_ID_MICRO_MEMORY_5425CN 0x5425 +#define PCI_DEVICE_ID_MICRO_MEMORY_6155 0x6155 + #define PCI_VENDOR_ID_DOMEX 0x134a #define PCI_DEVICE_ID_DOMEX_DMX3191D 0x0001 From 4e0af881afee2b399854b1cdfdbe37e6ab6a09ca Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Thu, 27 Sep 2007 06:41:25 -0400 Subject: [PATCH 23/37] drivers/block/umem: use dev_printk() dev_printk() gives us a consistent prefix (driver name + PCI bus id), which allows us to eliminate the hand-rolled one. Also allows us to eliminate card->card_number, which was used solely in printk() calls. Signed-off-by: Jeff Garzik --- drivers/block/umem.c | 111 ++++++++++++++++++++++++------------------- 1 file changed, 62 insertions(+), 49 deletions(-) diff --git a/drivers/block/umem.c b/drivers/block/umem.c index 33ef7661e1c1..32060b84c0fd 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c @@ -97,7 +97,6 @@ static int major_nr; #include struct cardinfo { - int card_number; struct pci_dev *dev; int irq; @@ -236,7 +235,7 @@ static void dump_regs(struct cardinfo *card) */ static void dump_dmastat(struct cardinfo *card, unsigned int dmastat) { - printk(KERN_DEBUG "MM%d*: DMAstat - ", card->card_number); + dev_printk(KERN_DEBUG, &card->dev->dev, "DMAstat - "); if (dmastat & DMASCR_ANY_ERR) printk("ANY_ERR "); if (dmastat & DMASCR_MBE_ERR) @@ -499,17 +498,17 @@ static void process_page(unsigned long data) if (control & DMASCR_HARD_ERROR) { /* error */ clear_bit(BIO_UPTODATE, &bio->bi_flags); - printk(KERN_WARNING "MM%d: I/O error on sector %d/%d\n", - card->card_number, - le32_to_cpu(desc->local_addr)>>9, - le32_to_cpu(desc->transfer_size)); + dev_printk(KERN_WARNING, &card->dev->dev, + "I/O error on sector %d/%d\n", + le32_to_cpu(desc->local_addr)>>9, + le32_to_cpu(desc->transfer_size)); dump_dmastat(card, control); } else if (test_bit(BIO_RW, &bio->bi_rw) && le32_to_cpu(desc->local_addr)>>9 == card->init_size) { card->init_size += le32_to_cpu(desc->transfer_size)>>9; if (card->init_size>>1 >= card->mm_size) { - printk(KERN_INFO "MM%d: memory now initialised\n", - card->card_number); + dev_printk(KERN_INFO, &card->dev->dev, + "memory now initialised\n"); set_userbit(card, MEMORY_INITIALIZED, 1); } } @@ -618,46 +617,51 @@ HW_TRACE(0x30); dump_dmastat(card, dma_status); if (stat & 0x01) - printk(KERN_ERR "MM%d*: Memory access error detected (err count %d)\n", - card->card_number, count); + dev_printk(KERN_ERR, &card->dev->dev, + "Memory access error detected (err count %d)\n", + count); if (stat & 0x02) - printk(KERN_ERR "MM%d*: Multi-bit EDC error\n", - card->card_number); + dev_printk(KERN_ERR, &card->dev->dev, + "Multi-bit EDC error\n"); - printk(KERN_ERR "MM%d*: Fault Address 0x%02x%08x, Fault Data 0x%08x%08x\n", - card->card_number, addr_log2, addr_log1, data_log2, data_log1); - printk(KERN_ERR "MM%d*: Fault Check 0x%02x, Fault Syndrome 0x%02x\n", - card->card_number, check, syndrome); + dev_printk(KERN_ERR, &card->dev->dev, + "Fault Address 0x%02x%08x, Fault Data 0x%08x%08x\n", + addr_log2, addr_log1, data_log2, data_log1); + dev_printk(KERN_ERR, &card->dev->dev, + "Fault Check 0x%02x, Fault Syndrome 0x%02x\n", + check, syndrome); writeb(0, card->csr_remap + ERROR_COUNT); } if (dma_status & DMASCR_PARITY_ERR_REP) { - printk(KERN_ERR "MM%d*: PARITY ERROR REPORTED\n", card->card_number); + dev_printk(KERN_ERR, &card->dev->dev, + "PARITY ERROR REPORTED\n"); pci_read_config_word(card->dev, PCI_STATUS, &cfg_status); pci_write_config_word(card->dev, PCI_STATUS, cfg_status); } if (dma_status & DMASCR_PARITY_ERR_DET) { - printk(KERN_ERR "MM%d*: PARITY ERROR DETECTED\n", card->card_number); + dev_printk(KERN_ERR, &card->dev->dev, + "PARITY ERROR DETECTED\n"); pci_read_config_word(card->dev, PCI_STATUS, &cfg_status); pci_write_config_word(card->dev, PCI_STATUS, cfg_status); } if (dma_status & DMASCR_SYSTEM_ERR_SIG) { - printk(KERN_ERR "MM%d*: SYSTEM ERROR\n", card->card_number); + dev_printk(KERN_ERR, &card->dev->dev, "SYSTEM ERROR\n"); pci_read_config_word(card->dev, PCI_STATUS, &cfg_status); pci_write_config_word(card->dev, PCI_STATUS, cfg_status); } if (dma_status & DMASCR_TARGET_ABT) { - printk(KERN_ERR "MM%d*: TARGET ABORT\n", card->card_number); + dev_printk(KERN_ERR, &card->dev->dev, "TARGET ABORT\n"); pci_read_config_word(card->dev, PCI_STATUS, &cfg_status); pci_write_config_word(card->dev, PCI_STATUS, cfg_status); } if (dma_status & DMASCR_MASTER_ABT) { - printk(KERN_ERR "MM%d*: MASTER ABORT\n", card->card_number); + dev_printk(KERN_ERR, &card->dev->dev, "MASTER ABORT\n"); pci_read_config_word(card->dev, PCI_STATUS, &cfg_status); pci_write_config_word(card->dev, PCI_STATUS, cfg_status); } @@ -708,20 +712,20 @@ static int check_battery(struct cardinfo *card, int battery, int status) card->battery[battery].last_change = jiffies; if (card->battery[battery].good) { - printk(KERN_ERR "MM%d: Battery %d now good\n", - card->card_number, battery + 1); + dev_printk(KERN_ERR, &card->dev->dev, + "Battery %d now good\n", battery + 1); card->battery[battery].warned = 0; } else - printk(KERN_ERR "MM%d: Battery %d now FAILED\n", - card->card_number, battery + 1); + dev_printk(KERN_ERR, &card->dev->dev, + "Battery %d now FAILED\n", battery + 1); return 1; } else if (!card->battery[battery].good && !card->battery[battery].warned && time_after_eq(jiffies, card->battery[battery].last_change + (HZ * 60 * 60 * 5))) { - printk(KERN_ERR "MM%d: Battery %d still FAILED after 5 hours\n", - card->card_number, battery + 1); + dev_printk(KERN_ERR, &card->dev->dev, + "Battery %d still FAILED after 5 hours\n", battery + 1); card->battery[battery].warned = 1; return 1; @@ -745,8 +749,8 @@ static void check_batteries(struct cardinfo *card) status = readb(card->csr_remap + MEMCTRLSTATUS_BATTERY); if (debug & DEBUG_BATTERY_POLLING) - printk(KERN_DEBUG "MM%d: checking battery status, 1 = %s, 2 = %s\n", - card->card_number, + dev_printk(KERN_DEBUG, &card->dev->dev, + "checking battery status, 1 = %s, 2 = %s\n", (status & BATTERY_1_FAILURE) ? "FAILURE" : "OK", (status & BATTERY_2_FAILURE) ? "FAILURE" : "OK"); @@ -866,6 +870,10 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i unsigned char batt_status; unsigned int saved_bar, data; int magic_number; + static int printed_version; + + if (!printed_version++) + printk(KERN_INFO DRIVER_VERSION " : " DRIVER_DESC "\n"); if (pci_enable_device(dev) < 0) return -ENODEV; @@ -874,21 +882,21 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i pci_set_master(dev); card->dev = dev; - card->card_number = num_cards; card->csr_base = pci_resource_start(dev, 0); card->csr_len = pci_resource_len(dev, 0); - printk(KERN_INFO "Micro Memory(tm) controller #%d found at %02x:%02x (PCI Mem Module (Battery Backup))\n", - card->card_number, dev->bus->number, dev->devfn); + dev_printk(KERN_INFO, &dev->dev, + "Micro Memory(tm) controller found (PCI Mem Module (Battery Backup))\n"); if (pci_set_dma_mask(dev, DMA_64BIT_MASK) && pci_set_dma_mask(dev, DMA_32BIT_MASK)) { - printk(KERN_WARNING "MM%d: NO suitable DMA found\n",num_cards); + dev_printk(KERN_WARNING, &dev->dev, "NO suitable DMA found\n"); return -ENOMEM; } if (!request_mem_region(card->csr_base, card->csr_len, "Micro Memory")) { - printk(KERN_ERR "MM%d: Unable to request memory region\n", card->card_number); + dev_printk(KERN_ERR, &card->dev->dev, + "Unable to request memory region\n"); ret = -ENOMEM; goto failed_req_csr; @@ -896,13 +904,15 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i card->csr_remap = ioremap_nocache(card->csr_base, card->csr_len); if (!card->csr_remap) { - printk(KERN_ERR "MM%d: Unable to remap memory region\n", card->card_number); + dev_printk(KERN_ERR, &card->dev->dev, + "Unable to remap memory region\n"); ret = -ENOMEM; goto failed_remap_csr; } - printk(KERN_INFO "MM%d: CSR 0x%08lx -> 0x%p (0x%lx)\n", card->card_number, + dev_printk(KERN_INFO, &card->dev->dev, + "CSR 0x%08lx -> 0x%p (0x%lx)\n", card->csr_base, card->csr_remap, card->csr_len); switch(card->dev->device) { @@ -927,7 +937,7 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i } if (readb(card->csr_remap + MEMCTRLSTATUS_MAGIC) != magic_number) { - printk(KERN_ERR "MM%d: Magic number invalid\n", card->card_number); + dev_printk(KERN_ERR, &card->dev->dev, "Magic number invalid\n"); ret = -ENOMEM; goto failed_magic; } @@ -940,7 +950,7 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i &card->mm_pages[1].page_dma); if (card->mm_pages[0].desc == NULL || card->mm_pages[1].desc == NULL) { - printk(KERN_ERR "MM%d: alloc failed\n", card->card_number); + dev_printk(KERN_ERR, &card->dev->dev, "alloc failed\n"); goto failed_alloc; } reset_page(&card->mm_pages[0]); @@ -995,11 +1005,12 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i card->battery[0].last_change = card->battery[1].last_change = jiffies; if (card->flags & UM_FLAG_NO_BATT) - printk(KERN_INFO "MM%d: Size %d KB\n", - card->card_number, card->mm_size); + dev_printk(KERN_INFO, &card->dev->dev, + "Size %d KB\n", card->mm_size); else { - printk(KERN_INFO "MM%d: Size %d KB, Battery 1 %s (%s), Battery 2 %s (%s)\n", - card->card_number, card->mm_size, + dev_printk(KERN_INFO, &card->dev->dev, + "Size %d KB, Battery 1 %s (%s), Battery 2 %s (%s)\n", + card->mm_size, (batt_status & BATTERY_1_DISABLED ? "Disabled" : "Enabled"), card->battery[0].good ? "OK" : "FAILURE", (batt_status & BATTERY_2_DISABLED ? "Disabled" : "Enabled"), @@ -1021,14 +1032,16 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i if (request_irq(dev->irq, mm_interrupt, IRQF_SHARED, "pci-umem", card)) { - printk(KERN_ERR "MM%d: Unable to allocate IRQ\n", card->card_number); + dev_printk(KERN_ERR, &card->dev->dev, + "Unable to allocate IRQ\n"); ret = -ENODEV; goto failed_req_irq; } card->irq = dev->irq; - printk(KERN_INFO "MM%d: Window size %d bytes, IRQ %d\n", card->card_number, + dev_printk(KERN_INFO, &card->dev->dev, + "Window size %d bytes, IRQ %d\n", card->win_size, card->irq); spin_lock_init(&card->lock); @@ -1049,10 +1062,12 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i num_cards++; if (!get_userbit(card, MEMORY_INITIALIZED)) { - printk(KERN_INFO "MM%d: memory NOT initialized. Consider over-writing whole device.\n", card->card_number); + dev_printk(KERN_INFO, &card->dev->dev, + "memory NOT initialized. Consider over-writing whole device.\n"); card->init_size = 0; } else { - printk(KERN_INFO "MM%d: memory already initialized\n", card->card_number); + dev_printk(KERN_INFO, &card->dev->dev, + "memory already initialized\n"); card->init_size = card->mm_size; } @@ -1137,8 +1152,6 @@ static int __init mm_init(void) int retval, i; int err; - printk(KERN_INFO DRIVER_VERSION " : " DRIVER_DESC "\n"); - retval = pci_register_driver(&mm_pci_driver); if (retval) return -ENOMEM; @@ -1169,7 +1182,7 @@ static int __init mm_init(void) } init_battery_timer(); - printk("MM: desc_per_page = %ld\n", DESC_PER_PAGE); + printk(KERN_INFO "MM: desc_per_page = %ld\n", DESC_PER_PAGE); /* printk("mm_init: Done. 10-19-01 9:00\n"); */ return 0; From ee4a7b6874469244ed0e3b8fde20028e0bb52642 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Thu, 27 Sep 2007 07:40:33 -0400 Subject: [PATCH 24/37] drivers/block/umem: minor cleanups * tab-align DRIVER_*, pci_driver entries * reduced wasted memory by killing unused struct cardinfo members * move free_irq() call above resource unmap, to fix tiny window where irq handler may access recently-unmapped memory * propagate pci_enable_device() return value * use pci_request_regions, pci_release_regions() for resource reservation * call pci_disable_device() in pci_driver::remove() Signed-off-by: Jeff Garzik --- drivers/block/umem.c | 59 ++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 30 deletions(-) diff --git a/drivers/block/umem.c b/drivers/block/umem.c index 32060b84c0fd..97c5dc9436a9 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c @@ -67,9 +67,10 @@ * Version Information */ -#define DRIVER_VERSION "v2.3" -#define DRIVER_AUTHOR "San Mehat, Johannes Erdfelt, NeilBrown" -#define DRIVER_DESC "Micro Memory(tm) PCI memory board block driver" +#define DRIVER_NAME "umem" +#define DRIVER_VERSION "v2.3" +#define DRIVER_AUTHOR "San Mehat, Johannes Erdfelt, NeilBrown" +#define DRIVER_DESC "Micro Memory(tm) PCI memory board block driver" static int debug; /* #define HW_TRACE(x) writeb(x,cards[0].csr_remap + MEMCTRLSTATUS_MAGIC) */ @@ -99,12 +100,7 @@ static int major_nr; struct cardinfo { struct pci_dev *dev; - int irq; - - unsigned long csr_base; unsigned char __iomem *csr_remap; - unsigned long csr_len; - unsigned int win_size; /* PCI window size */ unsigned int mm_size; /* size in kbytes */ unsigned int init_size; /* initial segment, in sectors, @@ -869,22 +865,27 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i unsigned char mem_present; unsigned char batt_status; unsigned int saved_bar, data; + unsigned long csr_base; + unsigned long csr_len; int magic_number; static int printed_version; if (!printed_version++) printk(KERN_INFO DRIVER_VERSION " : " DRIVER_DESC "\n"); - if (pci_enable_device(dev) < 0) - return -ENODEV; + ret = pci_enable_device(dev); + if (ret) + return ret; pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xF8); pci_set_master(dev); card->dev = dev; - card->csr_base = pci_resource_start(dev, 0); - card->csr_len = pci_resource_len(dev, 0); + csr_base = pci_resource_start(dev, 0); + csr_len = pci_resource_len(dev, 0); + if (!csr_base || !csr_len) + return -ENODEV; dev_printk(KERN_INFO, &dev->dev, "Micro Memory(tm) controller found (PCI Mem Module (Battery Backup))\n"); @@ -894,15 +895,15 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i dev_printk(KERN_WARNING, &dev->dev, "NO suitable DMA found\n"); return -ENOMEM; } - if (!request_mem_region(card->csr_base, card->csr_len, "Micro Memory")) { + + ret = pci_request_regions(dev, DRIVER_NAME); + if (ret) { dev_printk(KERN_ERR, &card->dev->dev, "Unable to request memory region\n"); - ret = -ENOMEM; - goto failed_req_csr; } - card->csr_remap = ioremap_nocache(card->csr_base, card->csr_len); + card->csr_remap = ioremap_nocache(csr_base, csr_len); if (!card->csr_remap) { dev_printk(KERN_ERR, &card->dev->dev, "Unable to remap memory region\n"); @@ -913,7 +914,7 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i dev_printk(KERN_INFO, &card->dev->dev, "CSR 0x%08lx -> 0x%p (0x%lx)\n", - card->csr_base, card->csr_remap, card->csr_len); + csr_base, card->csr_remap, csr_len); switch(card->dev->device) { case 0x5415: @@ -1028,9 +1029,6 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i data = ~data; data += 1; - card->win_size = data; - - if (request_irq(dev->irq, mm_interrupt, IRQF_SHARED, "pci-umem", card)) { dev_printk(KERN_ERR, &card->dev->dev, "Unable to allocate IRQ\n"); @@ -1039,10 +1037,8 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i goto failed_req_irq; } - card->irq = dev->irq; dev_printk(KERN_INFO, &card->dev->dev, - "Window size %d bytes, IRQ %d\n", - card->win_size, card->irq); + "Window size %d bytes, IRQ %d\n", data, dev->irq); spin_lock_init(&card->lock); @@ -1089,7 +1085,7 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i failed_magic: iounmap(card->csr_remap); failed_remap_csr: - release_mem_region(card->csr_base, card->csr_len); + pci_release_regions(dev); failed_req_csr: return ret; @@ -1104,9 +1100,8 @@ static void mm_pci_remove(struct pci_dev *dev) struct cardinfo *card = pci_get_drvdata(dev); tasklet_kill(&card->tasklet); + free_irq(dev->irq, card); iounmap(card->csr_remap); - release_mem_region(card->csr_base, card->csr_len); - free_irq(card->irq, card); if (card->mm_pages[0].desc) pci_free_consistent(card->dev, PAGE_SIZE*2, @@ -1117,6 +1112,9 @@ static void mm_pci_remove(struct pci_dev *dev) card->mm_pages[1].desc, card->mm_pages[1].page_dma); blk_cleanup_queue(card->queue); + + pci_release_regions(dev); + pci_disable_device(dev); } static const struct pci_device_id mm_pci_ids[] = { @@ -1136,11 +1134,12 @@ static const struct pci_device_id mm_pci_ids[] = { MODULE_DEVICE_TABLE(pci, mm_pci_ids); static struct pci_driver mm_pci_driver = { - .name = "umem", - .id_table = mm_pci_ids, - .probe = mm_pci_probe, - .remove = mm_pci_remove, + .name = DRIVER_NAME, + .id_table = mm_pci_ids, + .probe = mm_pci_probe, + .remove = mm_pci_remove, }; + /* ----------------------------------------------------------------------------------- -- mm_init From 4e953a216265f8646360fa909bdc87ea4bf446b3 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Thu, 27 Sep 2007 07:41:50 -0400 Subject: [PATCH 25/37] drivers/block/umem: trim trailing whitespace Signed-off-by: Jeff Garzik --- drivers/block/umem.c | 22 +++++++++++----------- drivers/block/umem.h | 14 +++++++------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/block/umem.c b/drivers/block/umem.c index 97c5dc9436a9..251041763690 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c @@ -293,7 +293,7 @@ static void mm_start_io(struct cardinfo *card) desc->control_bits &= ~cpu_to_le32(DMASCR_CHAIN_EN); desc->sem_control_bits = desc->control_bits; - + if (debug & DEBUG_LED_ON_TRANSFER) set_led(card, LED_REMOVE, LED_ON); @@ -327,7 +327,7 @@ static int add_bio(struct cardinfo *card); static void activate(struct cardinfo *card) { - /* if No page is Active, and Ready is + /* if No page is Active, and Ready is * not empty, then switch Ready page * to active and start IO. * Then add any bh's that are available to Ready @@ -366,7 +366,7 @@ static void mm_unplug_device(struct request_queue *q) spin_unlock_irqrestore(&card->lock, flags); } -/* +/* * If there is room on Ready page, take * one bh off list and add it. * return 1 if there was room, else 0. @@ -467,7 +467,7 @@ static void process_page(unsigned long data) if (card->Active < 0) goto out_unlock; page = &card->mm_pages[card->Active]; - + while (page->headcnt < page->cnt) { struct bio *bio = page->bio; struct mm_dma_desc *desc = &page->desc[page->headcnt]; @@ -477,7 +477,7 @@ static void process_page(unsigned long data) if (!(control & DMASCR_DMA_COMPLETE)) { control = dma_status; - last=1; + last=1; } page->headcnt++; idx = page->idx; @@ -487,7 +487,7 @@ static void process_page(unsigned long data) page->idx = page->bio->bi_idx; } - pci_unmap_page(card->dev, desc->data_dma_handle, + pci_unmap_page(card->dev, desc->data_dma_handle, bio_iovec_idx(bio,idx)->bv_len, (control& DMASCR_TRANSFER_READ) ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); @@ -592,7 +592,7 @@ HW_TRACE(0x30); else writeb((DMASCR_DMA_COMPLETE|DMASCR_CHAIN_COMPLETE) >> 16, card->csr_remap+ DMA_STATUS_CTRL + 2); - + /* log errors and clear interrupt status */ if (dma_status & DMASCR_ANY_ERR) { unsigned int data_log1, data_log2; @@ -668,7 +668,7 @@ HW_TRACE(0x30); HW_TRACE(0x36); - return IRQ_HANDLED; + return IRQ_HANDLED; } /* ----------------------------------------------------------------------------------- @@ -761,7 +761,7 @@ static void check_all_batteries(unsigned long ptr) { int i; - for (i = 0; i < num_cards; i++) + for (i = 0; i < num_cards; i++) if (!(cards[i].flags & UM_FLAG_NO_BATT)) { struct cardinfo *card = &cards[i]; spin_lock_bh(&card->lock); @@ -972,7 +972,7 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i tasklet_init(&card->tasklet, process_page, (unsigned long)card); card->check_batteries = 0; - + mem_present = readb(card->csr_remap + MEMCTRLSTATUS_MEMORY); switch (mem_present) { case MEM_128_MB: @@ -1005,7 +1005,7 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i card->battery[1].good = !(batt_status & BATTERY_2_FAILURE); card->battery[0].last_change = card->battery[1].last_change = jiffies; - if (card->flags & UM_FLAG_NO_BATT) + if (card->flags & UM_FLAG_NO_BATT) dev_printk(KERN_INFO, &card->dev->dev, "Size %d KB\n", card->mm_size); else { diff --git a/drivers/block/umem.h b/drivers/block/umem.h index 3a3819afed92..375c68974c9a 100644 --- a/drivers/block/umem.h +++ b/drivers/block/umem.h @@ -87,13 +87,13 @@ #define DMASCR_DMA_COMPLETE 0x40000 #define DMASCR_CHAIN_COMPLETE 0x80000 -/* -3.SOME PCs HAVE HOST BRIDGES WHICH APPARENTLY DO NOT CORRECTLY HANDLE -READ-LINE (0xE) OR READ-MULTIPLE (0xC) PCI COMMAND CODES DURING DMA -TRANSFERS. IN OTHER SYSTEMS THESE COMMAND CODES WILL CAUSE THE HOST BRIDGE -TO ALLOW LONGER BURSTS DURING DMA READ OPERATIONS. THE UPPER FOUR BITS -(31..28) OF THE DMA CSR HAVE BEEN MADE PROGRAMMABLE, SO THAT EITHER A 0x6, -AN 0xE OR A 0xC CAN BE WRITTEN TO THEM TO SET THE COMMAND CODE USED DURING +/* +3.SOME PCs HAVE HOST BRIDGES WHICH APPARENTLY DO NOT CORRECTLY HANDLE +READ-LINE (0xE) OR READ-MULTIPLE (0xC) PCI COMMAND CODES DURING DMA +TRANSFERS. IN OTHER SYSTEMS THESE COMMAND CODES WILL CAUSE THE HOST BRIDGE +TO ALLOW LONGER BURSTS DURING DMA READ OPERATIONS. THE UPPER FOUR BITS +(31..28) OF THE DMA CSR HAVE BEEN MADE PROGRAMMABLE, SO THAT EITHER A 0x6, +AN 0xE OR A 0xC CAN BE WRITTEN TO THEM TO SET THE COMMAND CODE USED DURING DMA READ OPERATIONS. */ #define DMASCR_READ 0x60000000 From cb3503ca54dc34e8dc3b823a6bd52c0807c102f4 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Thu, 27 Sep 2007 07:49:39 -0400 Subject: [PATCH 26/37] drivers/block/umem: use DRIVER_NAME where appropriate Signed-off-by: Jeff Garzik --- drivers/block/umem.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/block/umem.c b/drivers/block/umem.c index 251041763690..99806f9ee4ce 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c @@ -1029,7 +1029,7 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i data = ~data; data += 1; - if (request_irq(dev->irq, mm_interrupt, IRQF_SHARED, "pci-umem", card)) { + if (request_irq(dev->irq, mm_interrupt, IRQF_SHARED, DRIVER_NAME, card)) { dev_printk(KERN_ERR, &card->dev->dev, "Unable to allocate IRQ\n"); ret = -ENODEV; @@ -1155,7 +1155,7 @@ static int __init mm_init(void) if (retval) return -ENOMEM; - err = major_nr = register_blkdev(0, "umem"); + err = major_nr = register_blkdev(0, DRIVER_NAME); if (err < 0) { pci_unregister_driver(&mm_pci_driver); return -EIO; @@ -1187,7 +1187,7 @@ static int __init mm_init(void) out: pci_unregister_driver(&mm_pci_driver); - unregister_blkdev(major_nr, "umem"); + unregister_blkdev(major_nr, DRIVER_NAME); while (i--) put_disk(mm_gendisk[i]); return -ENOMEM; @@ -1210,7 +1210,7 @@ static void __exit mm_cleanup(void) pci_unregister_driver(&mm_pci_driver); - unregister_blkdev(major_nr, "umem"); + unregister_blkdev(major_nr, DRIVER_NAME); } module_init(mm_init); From 34e1b83413d91999416443f31c276095f9937aa6 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Thu, 4 Oct 2007 08:52:38 +0200 Subject: [PATCH 27/37] Sysace: Minor coding convention fixup Put function call and return code test on separate lines. Signed-off-by: Grant Likely Signed-off-by: Jens Axboe --- drivers/block/xsysace.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index 3ea172b7b7a4..3847464f5ea6 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c @@ -1091,7 +1091,8 @@ ace_alloc(struct device *dev, int id, unsigned long physaddr, ace->bus_width = bus_width; /* Call the setup code */ - if ((rc = ace_setup(ace)) != 0) + rc = ace_setup(ace); + if (rc) goto err_setup; dev_set_drvdata(dev, ace); @@ -1253,11 +1254,13 @@ static int __init ace_init(void) goto err_blk; } - if ((rc = ace_of_register()) != 0) + rc = ace_of_register(); + if (rc) goto err_of; pr_debug("xsysace: registering platform binding\n"); - if ((rc = platform_driver_register(&ace_platform_driver)) != 0) + rc = platform_driver_register(&ace_platform_driver); + if (rc) goto err_plat; pr_info("Xilinx SystemACE device driver, major=%i\n", ace_major); From b5515d86f2efd4dd3516c16c17c1a611a5800b19 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Thu, 4 Oct 2007 08:52:39 +0200 Subject: [PATCH 28/37] Sysace: sparse fixes Signed-off-by: Grant Likely Signed-off-by: Jens Axboe --- drivers/block/xsysace.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index 3847464f5ea6..5b73471ada78 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c @@ -195,7 +195,7 @@ struct ace_device { /* Details of hardware device */ unsigned long physaddr; - void *baseaddr; + void __iomem *baseaddr; int irq; int bus_width; /* 0 := 8 bit; 1 := 16 bit */ struct ace_reg_ops *reg_ops; @@ -227,20 +227,20 @@ struct ace_reg_ops { /* 8 Bit bus width */ static u16 ace_in_8(struct ace_device *ace, int reg) { - void *r = ace->baseaddr + reg; + void __iomem *r = ace->baseaddr + reg; return in_8(r) | (in_8(r + 1) << 8); } static void ace_out_8(struct ace_device *ace, int reg, u16 val) { - void *r = ace->baseaddr + reg; + void __iomem *r = ace->baseaddr + reg; out_8(r, val); out_8(r + 1, val >> 8); } static void ace_datain_8(struct ace_device *ace) { - void *r = ace->baseaddr + 0x40; + void __iomem *r = ace->baseaddr + 0x40; u8 *dst = ace->data_ptr; int i = ACE_FIFO_SIZE; while (i--) @@ -250,7 +250,7 @@ static void ace_datain_8(struct ace_device *ace) static void ace_dataout_8(struct ace_device *ace) { - void *r = ace->baseaddr + 0x40; + void __iomem *r = ace->baseaddr + 0x40; u8 *src = ace->data_ptr; int i = ACE_FIFO_SIZE; while (i--) From d2bbf3da3759d04cd5836955cc59c8ae96092831 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Thu, 4 Oct 2007 08:52:40 +0200 Subject: [PATCH 29/37] Sysace: Don't enable IRQ until after interrupt handler is registered The previous patch to move the interrupt handler registration moved it below enabling interrupts which could be a problem if the device is on a shared interrupt line. This patch fixes the order. Signed-off-by: Grant Likely Signed-off-by: Jens Axboe --- drivers/block/xsysace.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index 5b73471ada78..9e7652dcde6c 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c @@ -1005,11 +1005,6 @@ static int __devinit ace_setup(struct ace_device *ace) ace_out(ace, ACE_CTRL, ACE_CTRL_FORCECFGMODE | ACE_CTRL_DATABUFRDYIRQ | ACE_CTRL_ERRORIRQ); - /* Enable interrupts */ - val = ace_in(ace, ACE_CTRL); - val |= ACE_CTRL_DATABUFRDYIRQ | ACE_CTRL_ERRORIRQ; - ace_out(ace, ACE_CTRL, val); - /* Now we can hook up the irq handler */ if (ace->irq != NO_IRQ) { rc = request_irq(ace->irq, ace_interrupt, 0, "systemace", ace); @@ -1020,6 +1015,11 @@ static int __devinit ace_setup(struct ace_device *ace) } } + /* Enable interrupts */ + val = ace_in(ace, ACE_CTRL); + val |= ACE_CTRL_DATABUFRDYIRQ | ACE_CTRL_ERRORIRQ; + ace_out(ace, ACE_CTRL, val); + /* Print the identification */ dev_info(ace->dev, "Xilinx SystemACE revision %i.%i.%i\n", (version >> 12) & 0xf, (version >> 8) & 0x0f, version & 0xff); From f58c4c0a17e500e767473598b3deafaa1d64051d Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 9 Oct 2007 13:23:51 +0200 Subject: [PATCH 30/37] compat_ioctl: move common block ioctls to compat_blkdev_ioctl Make compat_blkdev_ioctl and blkdev_ioctl reflect the respective native versions. This is somewhat more efficient and makes it easier to keep the two in sync. Also get rid of the bogus handling for broken_blkgetsize and the duplicate entry for BLKRASET. Signed-off-by: Arnd Bergmann Signed-off-by: Jens Axboe --- block/Makefile | 1 + block/compat_ioctl.c | 121 +++++++++++++++++++++++++++++++++++++++++++ block/ioctl.c | 21 ++------ fs/compat_ioctl.c | 45 ---------------- 4 files changed, 126 insertions(+), 62 deletions(-) create mode 100644 block/compat_ioctl.c diff --git a/block/Makefile b/block/Makefile index 959feeb253be..3cfe7cebaa6a 100644 --- a/block/Makefile +++ b/block/Makefile @@ -11,3 +11,4 @@ obj-$(CONFIG_IOSCHED_DEADLINE) += deadline-iosched.o obj-$(CONFIG_IOSCHED_CFQ) += cfq-iosched.o obj-$(CONFIG_BLK_DEV_IO_TRACE) += blktrace.o +obj-$(CONFIG_COMPAT) += compat_ioctl.o diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c new file mode 100644 index 000000000000..d20fdb436f68 --- /dev/null +++ b/block/compat_ioctl.c @@ -0,0 +1,121 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int compat_put_ushort(unsigned long arg, unsigned short val) +{ + return put_user(val, (unsigned short __user *)compat_ptr(arg)); +} + +static int compat_put_int(unsigned long arg, int val) +{ + return put_user(val, (compat_int_t __user *)compat_ptr(arg)); +} + +static int compat_put_long(unsigned long arg, long val) +{ + return put_user(val, (compat_long_t __user *)compat_ptr(arg)); +} + +static int compat_put_ulong(unsigned long arg, compat_ulong_t val) +{ + return put_user(val, (compat_ulong_t __user *)compat_ptr(arg)); +} + +static int compat_put_u64(unsigned long arg, u64 val) +{ + return put_user(val, (compat_u64 __user *)compat_ptr(arg)); +} + +#define BLKBSZGET_32 _IOR(0x12, 112, int) +#define BLKBSZSET_32 _IOW(0x12, 113, int) +#define BLKGETSIZE64_32 _IOR(0x12, 114, int) + +static int compat_blkdev_locked_ioctl(struct inode *inode, struct file *file, + struct block_device *bdev, + unsigned cmd, unsigned long arg) +{ + struct backing_dev_info *bdi; + + switch (cmd) { + case BLKRAGET: + case BLKFRAGET: + if (!arg) + return -EINVAL; + bdi = blk_get_backing_dev_info(bdev); + if (bdi == NULL) + return -ENOTTY; + return compat_put_long(arg, + (bdi->ra_pages * PAGE_CACHE_SIZE) / 512); + case BLKROGET: /* compatible */ + return compat_put_int(arg, bdev_read_only(bdev) != 0); + case BLKBSZGET_32: /* get the logical block size (cf. BLKSSZGET) */ + return compat_put_int(arg, block_size(bdev)); + case BLKSSZGET: /* get block device hardware sector size */ + return compat_put_int(arg, bdev_hardsect_size(bdev)); + case BLKSECTGET: + return compat_put_ushort(arg, + bdev_get_queue(bdev)->max_sectors); + case BLKRASET: /* compatible, but no compat_ptr (!) */ + case BLKFRASET: + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + bdi = blk_get_backing_dev_info(bdev); + if (bdi == NULL) + return -ENOTTY; + bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE; + return 0; + case BLKGETSIZE: + if ((bdev->bd_inode->i_size >> 9) > ~0UL) + return -EFBIG; + return compat_put_ulong(arg, bdev->bd_inode->i_size >> 9); + + case BLKGETSIZE64_32: + return compat_put_u64(arg, bdev->bd_inode->i_size); + } + return -ENOIOCTLCMD; +} + +/* Most of the generic ioctls are handled in the normal fallback path. + This assumes the blkdev's low level compat_ioctl always returns + ENOIOCTLCMD for unknown ioctls. */ +long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg) +{ + int ret = -ENOIOCTLCMD; + struct inode *inode = file->f_mapping->host; + struct block_device *bdev = inode->i_bdev; + struct gendisk *disk = bdev->bd_disk; + + switch (cmd) { + case BLKFLSBUF: + case BLKROSET: + /* + * the ones below are implemented in blkdev_locked_ioctl, + * but we call blkdev_ioctl, which gets the lock for us + */ + case BLKRRPART: + return blkdev_ioctl(inode, file, cmd, + (unsigned long)compat_ptr(arg)); + case BLKBSZSET_32: + return blkdev_ioctl(inode, file, BLKBSZSET, + (unsigned long)compat_ptr(arg)); + } + + lock_kernel(); + ret = compat_blkdev_locked_ioctl(inode, file, bdev, cmd, arg); + /* FIXME: why do we assume -> compat_ioctl needs the BKL? */ + if (ret == -ENOIOCTLCMD && disk->fops->compat_ioctl) + ret = disk->fops->compat_ioctl(file, cmd, arg); + unlock_kernel(); + + return ret; +} diff --git a/block/ioctl.c b/block/ioctl.c index f7e3e8abf887..52d6385216ad 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -217,6 +217,10 @@ int blkdev_driver_ioctl(struct inode *inode, struct file *file, } EXPORT_SYMBOL_GPL(blkdev_driver_ioctl); +/* + * always keep this in sync with compat_blkdev_ioctl() and + * compat_blkdev_locked_ioctl() + */ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd, unsigned long arg) { @@ -284,21 +288,4 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd, return blkdev_driver_ioctl(inode, file, disk, cmd, arg); } - -/* Most of the generic ioctls are handled in the normal fallback path. - This assumes the blkdev's low level compat_ioctl always returns - ENOIOCTLCMD for unknown ioctls. */ -long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg) -{ - struct block_device *bdev = file->f_path.dentry->d_inode->i_bdev; - struct gendisk *disk = bdev->bd_disk; - int ret = -ENOIOCTLCMD; - if (disk->fops->compat_ioctl) { - lock_kernel(); - ret = disk->fops->compat_ioctl(file, cmd, arg); - unlock_kernel(); - } - return ret; -} - EXPORT_SYMBOL_GPL(blkdev_ioctl); diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 37310b0e8107..6be121868c60 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -1537,12 +1537,6 @@ ret_einval(unsigned int fd, unsigned int cmd, unsigned long arg) } #ifdef CONFIG_BLOCK -static int broken_blkgetsize(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - /* The mkswap binary hard codes it to Intel value :-((( */ - return w_long(fd, BLKGETSIZE, arg); -} - struct blkpg_ioctl_arg32 { compat_int_t op; compat_int_t flags; @@ -1578,29 +1572,6 @@ static int ioc_settimeout(unsigned int fd, unsigned int cmd, unsigned long arg) return rw_long(fd, AUTOFS_IOC_SETTIMEOUT, arg); } -#ifdef CONFIG_BLOCK -/* Fix sizeof(sizeof()) breakage */ -#define BLKBSZGET_32 _IOR(0x12,112,int) -#define BLKBSZSET_32 _IOW(0x12,113,int) -#define BLKGETSIZE64_32 _IOR(0x12,114,int) - -static int do_blkbszget(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - return sys_ioctl(fd, BLKBSZGET, (unsigned long)compat_ptr(arg)); -} - -static int do_blkbszset(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - return sys_ioctl(fd, BLKBSZSET, (unsigned long)compat_ptr(arg)); -} - -static int do_blkgetsize64(unsigned int fd, unsigned int cmd, - unsigned long arg) -{ - return sys_ioctl(fd, BLKGETSIZE64, (unsigned long)compat_ptr(arg)); -} -#endif - /* Bluetooth ioctls */ #define HCIUARTSETPROTO _IOW('U', 200, int) #define HCIUARTGETPROTO _IOR('U', 201, int) @@ -2546,19 +2517,11 @@ COMPATIBLE_IOCTL(FDFMTTRK) COMPATIBLE_IOCTL(FDRAWCMD) /* 0x12 */ #ifdef CONFIG_BLOCK -COMPATIBLE_IOCTL(BLKRASET) -COMPATIBLE_IOCTL(BLKROSET) -COMPATIBLE_IOCTL(BLKROGET) -COMPATIBLE_IOCTL(BLKRRPART) -COMPATIBLE_IOCTL(BLKFLSBUF) COMPATIBLE_IOCTL(BLKSECTSET) -COMPATIBLE_IOCTL(BLKSSZGET) COMPATIBLE_IOCTL(BLKTRACESTART) COMPATIBLE_IOCTL(BLKTRACESTOP) COMPATIBLE_IOCTL(BLKTRACESETUP) COMPATIBLE_IOCTL(BLKTRACETEARDOWN) -ULONG_IOCTL(BLKRASET) -ULONG_IOCTL(BLKFRASET) #endif /* RAID */ COMPATIBLE_IOCTL(RAID_VERSION) @@ -3337,11 +3300,6 @@ HANDLE_IOCTL(SIOCGSTAMPNS, do_siocgstampns) #endif #ifdef CONFIG_BLOCK HANDLE_IOCTL(HDIO_GETGEO, hdio_getgeo) -HANDLE_IOCTL(BLKRAGET, w_long) -HANDLE_IOCTL(BLKGETSIZE, w_long) -HANDLE_IOCTL(0x1260, broken_blkgetsize) -HANDLE_IOCTL(BLKFRAGET, w_long) -HANDLE_IOCTL(BLKSECTGET, w_long) HANDLE_IOCTL(BLKPG, blkpg_ioctl_trans) HANDLE_IOCTL(HDIO_GET_UNMASKINTR, hdio_ioctl_trans) HANDLE_IOCTL(HDIO_GET_MULTCOUNT, hdio_ioctl_trans) @@ -3415,9 +3373,6 @@ HANDLE_IOCTL(SONET_GETFRAMING, do_atm_ioctl) HANDLE_IOCTL(SONET_GETFRSENSE, do_atm_ioctl) /* block stuff */ #ifdef CONFIG_BLOCK -HANDLE_IOCTL(BLKBSZGET_32, do_blkbszget) -HANDLE_IOCTL(BLKBSZSET_32, do_blkbszset) -HANDLE_IOCTL(BLKGETSIZE64_32, do_blkgetsize64) /* Raw devices */ HANDLE_IOCTL(RAW_SETBIND, raw_ioctl) HANDLE_IOCTL(RAW_GETBIND, raw_ioctl) From 7199d4cdd8485f802df3e1bc131245c69009b9a4 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 9 Oct 2007 13:23:52 +0200 Subject: [PATCH 31/37] compat_ioctl: add compat_blkdev_driver_ioctl() Handle those blockdev ioctl calls that are compatible directly from the compat_blkdev_ioctl() function, instead of having to go through the compat_ioctl hash lookup. Signed-off-by: Arnd Bergmann Signed-off-by: Jens Axboe --- block/compat_ioctl.c | 121 ++++++++++++++++++++++++++++++++++++++++++- fs/compat_ioctl.c | 83 ----------------------------- 2 files changed, 120 insertions(+), 84 deletions(-) diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c index d20fdb436f68..500cc9e761c1 100644 --- a/block/compat_ioctl.c +++ b/block/compat_ioctl.c @@ -40,6 +40,122 @@ static int compat_put_u64(unsigned long arg, u64 val) #define BLKBSZSET_32 _IOW(0x12, 113, int) #define BLKGETSIZE64_32 _IOR(0x12, 114, int) +static int compat_blkdev_driver_ioctl(struct inode *inode, struct file *file, + struct gendisk *disk, unsigned cmd, unsigned long arg) +{ + int ret; + + switch (arg) { + /* + * No handler required for the ones below, we just need to + * convert arg to a 64 bit pointer. + */ + case BLKSECTSET: + /* + * 0x03 -- HD/IDE ioctl's used by hdparm and friends. + * Some need translations, these do not. + */ + case HDIO_GET_IDENTITY: + case HDIO_DRIVE_TASK: + case HDIO_DRIVE_CMD: + case HDIO_SCAN_HWIF: + /* 0x330 is reserved -- it used to be HDIO_GETGEO_BIG */ + case 0x330: + /* 0x02 -- Floppy ioctls */ + case FDMSGON: + case FDMSGOFF: + case FDSETEMSGTRESH: + case FDFLUSH: + case FDWERRORCLR: + case FDSETMAXERRS: + case FDGETMAXERRS: + case FDGETDRVTYP: + case FDEJECT: + case FDCLRPRM: + case FDFMTBEG: + case FDFMTEND: + case FDRESET: + case FDTWADDLE: + case FDFMTTRK: + case FDRAWCMD: + /* CDROM stuff */ + case CDROMPAUSE: + case CDROMRESUME: + case CDROMPLAYMSF: + case CDROMPLAYTRKIND: + case CDROMREADTOCHDR: + case CDROMREADTOCENTRY: + case CDROMSTOP: + case CDROMSTART: + case CDROMEJECT: + case CDROMVOLCTRL: + case CDROMSUBCHNL: + case CDROMMULTISESSION: + case CDROM_GET_MCN: + case CDROMRESET: + case CDROMVOLREAD: + case CDROMSEEK: + case CDROMPLAYBLK: + case CDROMCLOSETRAY: + case CDROM_DISC_STATUS: + case CDROM_CHANGER_NSLOTS: + case CDROM_GET_CAPABILITY: + /* Ignore cdrom.h about these next 5 ioctls, they absolutely do + * not take a struct cdrom_read, instead they take a struct cdrom_msf + * which is compatible. + */ + case CDROMREADMODE2: + case CDROMREADMODE1: + case CDROMREADRAW: + case CDROMREADCOOKED: + case CDROMREADALL: + /* DVD ioctls */ + case DVD_READ_STRUCT: + case DVD_WRITE_STRUCT: + case DVD_AUTH: + arg = (unsigned long)compat_ptr(arg); + /* These intepret arg as an unsigned long, not as a pointer, + * so we must not do compat_ptr() conversion. */ + case HDIO_SET_MULTCOUNT: + case HDIO_SET_UNMASKINTR: + case HDIO_SET_KEEPSETTINGS: + case HDIO_SET_32BIT: + case HDIO_SET_NOWERR: + case HDIO_SET_DMA: + case HDIO_SET_PIO_MODE: + case HDIO_SET_NICE: + case HDIO_SET_WCACHE: + case HDIO_SET_ACOUSTIC: + case HDIO_SET_BUSSTATE: + case HDIO_SET_ADDRESS: + case CDROMEJECT_SW: + case CDROM_SET_OPTIONS: + case CDROM_CLEAR_OPTIONS: + case CDROM_SELECT_SPEED: + case CDROM_SELECT_DISC: + case CDROM_MEDIA_CHANGED: + case CDROM_DRIVE_STATUS: + case CDROM_LOCKDOOR: + case CDROM_DEBUG: + break; + default: + /* unknown ioctl number */ + return -ENOIOCTLCMD; + } + + if (disk->fops->unlocked_ioctl) + return disk->fops->unlocked_ioctl(file, cmd, arg); + + if (disk->fops->ioctl) { + lock_kernel(); + ret = disk->fops->ioctl(inode, file, cmd, arg); + unlock_kernel(); + return ret; + } + + return -ENOTTY; +} + static int compat_blkdev_locked_ioctl(struct inode *inode, struct file *file, struct block_device *bdev, unsigned cmd, unsigned long arg) @@ -117,5 +233,8 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg) ret = disk->fops->compat_ioctl(file, cmd, arg); unlock_kernel(); - return ret; + if (ret != -ENOIOCTLCMD) + return ret; + + return compat_blkdev_driver_ioctl(inode, file, disk, cmd, arg); } diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 6be121868c60..16d681c331f9 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -2477,47 +2477,8 @@ COMPATIBLE_IOCTL(FIONREAD) /* This is also TIOCINQ */ /* 0x00 */ COMPATIBLE_IOCTL(FIBMAP) COMPATIBLE_IOCTL(FIGETBSZ) -/* 0x03 -- HD/IDE ioctl's used by hdparm and friends. - * Some need translations, these do not. - */ -COMPATIBLE_IOCTL(HDIO_GET_IDENTITY) -COMPATIBLE_IOCTL(HDIO_DRIVE_TASK) -COMPATIBLE_IOCTL(HDIO_DRIVE_CMD) -ULONG_IOCTL(HDIO_SET_MULTCOUNT) -ULONG_IOCTL(HDIO_SET_UNMASKINTR) -ULONG_IOCTL(HDIO_SET_KEEPSETTINGS) -ULONG_IOCTL(HDIO_SET_32BIT) -ULONG_IOCTL(HDIO_SET_NOWERR) -ULONG_IOCTL(HDIO_SET_DMA) -ULONG_IOCTL(HDIO_SET_PIO_MODE) -ULONG_IOCTL(HDIO_SET_NICE) -ULONG_IOCTL(HDIO_SET_WCACHE) -ULONG_IOCTL(HDIO_SET_ACOUSTIC) -ULONG_IOCTL(HDIO_SET_BUSSTATE) -ULONG_IOCTL(HDIO_SET_ADDRESS) -COMPATIBLE_IOCTL(HDIO_SCAN_HWIF) -/* 0x330 is reserved -- it used to be HDIO_GETGEO_BIG */ -COMPATIBLE_IOCTL(0x330) -/* 0x02 -- Floppy ioctls */ -COMPATIBLE_IOCTL(FDMSGON) -COMPATIBLE_IOCTL(FDMSGOFF) -COMPATIBLE_IOCTL(FDSETEMSGTRESH) -COMPATIBLE_IOCTL(FDFLUSH) -COMPATIBLE_IOCTL(FDWERRORCLR) -COMPATIBLE_IOCTL(FDSETMAXERRS) -COMPATIBLE_IOCTL(FDGETMAXERRS) -COMPATIBLE_IOCTL(FDGETDRVTYP) -COMPATIBLE_IOCTL(FDEJECT) -COMPATIBLE_IOCTL(FDCLRPRM) -COMPATIBLE_IOCTL(FDFMTBEG) -COMPATIBLE_IOCTL(FDFMTEND) -COMPATIBLE_IOCTL(FDRESET) -COMPATIBLE_IOCTL(FDTWADDLE) -COMPATIBLE_IOCTL(FDFMTTRK) -COMPATIBLE_IOCTL(FDRAWCMD) /* 0x12 */ #ifdef CONFIG_BLOCK -COMPATIBLE_IOCTL(BLKSECTSET) COMPATIBLE_IOCTL(BLKTRACESTART) COMPATIBLE_IOCTL(BLKTRACESTOP) COMPATIBLE_IOCTL(BLKTRACESETUP) @@ -2770,50 +2731,6 @@ COMPATIBLE_IOCTL(PPGETMODE) COMPATIBLE_IOCTL(PPGETPHASE) COMPATIBLE_IOCTL(PPGETFLAGS) COMPATIBLE_IOCTL(PPSETFLAGS) -/* CDROM stuff */ -COMPATIBLE_IOCTL(CDROMPAUSE) -COMPATIBLE_IOCTL(CDROMRESUME) -COMPATIBLE_IOCTL(CDROMPLAYMSF) -COMPATIBLE_IOCTL(CDROMPLAYTRKIND) -COMPATIBLE_IOCTL(CDROMREADTOCHDR) -COMPATIBLE_IOCTL(CDROMREADTOCENTRY) -COMPATIBLE_IOCTL(CDROMSTOP) -COMPATIBLE_IOCTL(CDROMSTART) -COMPATIBLE_IOCTL(CDROMEJECT) -COMPATIBLE_IOCTL(CDROMVOLCTRL) -COMPATIBLE_IOCTL(CDROMSUBCHNL) -ULONG_IOCTL(CDROMEJECT_SW) -COMPATIBLE_IOCTL(CDROMMULTISESSION) -COMPATIBLE_IOCTL(CDROM_GET_MCN) -COMPATIBLE_IOCTL(CDROMRESET) -COMPATIBLE_IOCTL(CDROMVOLREAD) -COMPATIBLE_IOCTL(CDROMSEEK) -COMPATIBLE_IOCTL(CDROMPLAYBLK) -COMPATIBLE_IOCTL(CDROMCLOSETRAY) -ULONG_IOCTL(CDROM_SET_OPTIONS) -ULONG_IOCTL(CDROM_CLEAR_OPTIONS) -ULONG_IOCTL(CDROM_SELECT_SPEED) -ULONG_IOCTL(CDROM_SELECT_DISC) -ULONG_IOCTL(CDROM_MEDIA_CHANGED) -ULONG_IOCTL(CDROM_DRIVE_STATUS) -COMPATIBLE_IOCTL(CDROM_DISC_STATUS) -COMPATIBLE_IOCTL(CDROM_CHANGER_NSLOTS) -ULONG_IOCTL(CDROM_LOCKDOOR) -ULONG_IOCTL(CDROM_DEBUG) -COMPATIBLE_IOCTL(CDROM_GET_CAPABILITY) -/* Ignore cdrom.h about these next 5 ioctls, they absolutely do - * not take a struct cdrom_read, instead they take a struct cdrom_msf - * which is compatible. - */ -COMPATIBLE_IOCTL(CDROMREADMODE2) -COMPATIBLE_IOCTL(CDROMREADMODE1) -COMPATIBLE_IOCTL(CDROMREADRAW) -COMPATIBLE_IOCTL(CDROMREADCOOKED) -COMPATIBLE_IOCTL(CDROMREADALL) -/* DVD ioctls */ -COMPATIBLE_IOCTL(DVD_READ_STRUCT) -COMPATIBLE_IOCTL(DVD_WRITE_STRUCT) -COMPATIBLE_IOCTL(DVD_AUTH) /* pktcdvd */ COMPATIBLE_IOCTL(PACKET_CTRL_CMD) /* Big A */ From 171044d449611c6e5040b37210ff6aba47f33ee4 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 9 Oct 2007 13:23:53 +0200 Subject: [PATCH 32/37] compat_ioctl: handle blk_trace ioctls blk_trace_setup is broken on x86_64 compat systems, this makes the code work correctly on all 64 bit architectures in compat mode. Signed-off-by: Arnd Bergmann Signed-off-by: Jens Axboe --- block/blktrace.c | 54 +++++++++++++++++++++++------------- block/compat_ioctl.c | 54 ++++++++++++++++++++++++++++++++++++ fs/compat_ioctl.c | 8 ------ include/linux/blktrace_api.h | 7 ++++- 4 files changed, 94 insertions(+), 29 deletions(-) diff --git a/block/blktrace.c b/block/blktrace.c index 20fa034ea4a2..775471ef84a5 100644 --- a/block/blktrace.c +++ b/block/blktrace.c @@ -312,33 +312,26 @@ static struct rchan_callbacks blk_relay_callbacks = { /* * Setup everything required to start tracing */ -static int blk_trace_setup(struct request_queue *q, struct block_device *bdev, - char __user *arg) +int do_blk_trace_setup(struct request_queue *q, struct block_device *bdev, + struct blk_user_trace_setup *buts) { - struct blk_user_trace_setup buts; struct blk_trace *old_bt, *bt = NULL; struct dentry *dir = NULL; char b[BDEVNAME_SIZE]; int ret, i; - if (copy_from_user(&buts, arg, sizeof(buts))) - return -EFAULT; - - if (!buts.buf_size || !buts.buf_nr) + if (!buts->buf_size || !buts->buf_nr) return -EINVAL; - strcpy(buts.name, bdevname(bdev, b)); + strcpy(buts->name, bdevname(bdev, b)); /* * some device names have larger paths - convert the slashes * to underscores for this to work as expected */ - for (i = 0; i < strlen(buts.name); i++) - if (buts.name[i] == '/') - buts.name[i] = '_'; - - if (copy_to_user(arg, &buts, sizeof(buts))) - return -EFAULT; + for (i = 0; i < strlen(buts->name); i++) + if (buts->name[i] == '/') + buts->name[i] = '_'; ret = -ENOMEM; bt = kzalloc(sizeof(*bt), GFP_KERNEL); @@ -350,7 +343,7 @@ static int blk_trace_setup(struct request_queue *q, struct block_device *bdev, goto err; ret = -ENOENT; - dir = blk_create_tree(buts.name); + dir = blk_create_tree(buts->name); if (!dir) goto err; @@ -363,20 +356,21 @@ static int blk_trace_setup(struct request_queue *q, struct block_device *bdev, if (!bt->dropped_file) goto err; - bt->rchan = relay_open("trace", dir, buts.buf_size, buts.buf_nr, &blk_relay_callbacks, bt); + bt->rchan = relay_open("trace", dir, buts->buf_size, + buts->buf_nr, &blk_relay_callbacks, bt); if (!bt->rchan) goto err; - bt->act_mask = buts.act_mask; + bt->act_mask = buts->act_mask; if (!bt->act_mask) bt->act_mask = (u16) -1; - bt->start_lba = buts.start_lba; - bt->end_lba = buts.end_lba; + bt->start_lba = buts->start_lba; + bt->end_lba = buts->end_lba; if (!bt->end_lba) bt->end_lba = -1ULL; - bt->pid = buts.pid; + bt->pid = buts->pid; bt->trace_state = Blktrace_setup; ret = -EBUSY; @@ -401,6 +395,26 @@ err: return ret; } +static int blk_trace_setup(struct request_queue *q, struct block_device *bdev, + char __user *arg) +{ + struct blk_user_trace_setup buts; + int ret; + + ret = copy_from_user(&buts, arg, sizeof(buts)); + if (ret) + return -EFAULT; + + ret = do_blk_trace_setup(q, bdev, &buts); + if (ret) + return ret; + + if (copy_to_user(arg, &buts, sizeof(buts))) + return -EFAULT; + + return 0; +} + static int blk_trace_startstop(struct request_queue *q, int start) { struct blk_trace *bt; diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c index 500cc9e761c1..219b7e76e8ad 100644 --- a/block/compat_ioctl.c +++ b/block/compat_ioctl.c @@ -40,6 +40,53 @@ static int compat_put_u64(unsigned long arg, u64 val) #define BLKBSZSET_32 _IOW(0x12, 113, int) #define BLKGETSIZE64_32 _IOR(0x12, 114, int) +struct compat_blk_user_trace_setup { + char name[32]; + u16 act_mask; + u32 buf_size; + u32 buf_nr; + compat_u64 start_lba; + compat_u64 end_lba; + u32 pid; +}; +#define BLKTRACESETUP32 _IOWR(0x12, 115, struct compat_blk_user_trace_setup) + +static int compat_blk_trace_setup(struct block_device *bdev, char __user *arg) +{ + struct blk_user_trace_setup buts; + struct compat_blk_user_trace_setup cbuts; + struct request_queue *q; + int ret; + + q = bdev_get_queue(bdev); + if (!q) + return -ENXIO; + + if (copy_from_user(&cbuts, arg, sizeof(cbuts))) + return -EFAULT; + + buts = (struct blk_user_trace_setup) { + .act_mask = cbuts.act_mask, + .buf_size = cbuts.buf_size, + .buf_nr = cbuts.buf_nr, + .start_lba = cbuts.start_lba, + .end_lba = cbuts.end_lba, + .pid = cbuts.pid, + }; + memcpy(&buts.name, &cbuts.name, 32); + + mutex_lock(&bdev->bd_mutex); + ret = do_blk_trace_setup(q, bdev, &buts); + mutex_unlock(&bdev->bd_mutex); + if (ret) + return ret; + + if (copy_to_user(arg, &buts.name, 32)) + return -EFAULT; + + return 0; +} + static int compat_blkdev_driver_ioctl(struct inode *inode, struct file *file, struct gendisk *disk, unsigned cmd, unsigned long arg) { @@ -197,6 +244,13 @@ static int compat_blkdev_locked_ioctl(struct inode *inode, struct file *file, case BLKGETSIZE64_32: return compat_put_u64(arg, bdev->bd_inode->i_size); + + case BLKTRACESETUP32: + return compat_blk_trace_setup(bdev, compat_ptr(arg)); + case BLKTRACESTART: /* compatible */ + case BLKTRACESTOP: /* compatible */ + case BLKTRACETEARDOWN: /* compatible */ + return blk_trace_ioctl(bdev, cmd, compat_ptr(arg)); } return -ENOIOCTLCMD; } diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 16d681c331f9..71065603a581 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -62,7 +62,6 @@ #include #include #include -#include #include #include @@ -2477,13 +2476,6 @@ COMPATIBLE_IOCTL(FIONREAD) /* This is also TIOCINQ */ /* 0x00 */ COMPATIBLE_IOCTL(FIBMAP) COMPATIBLE_IOCTL(FIGETBSZ) -/* 0x12 */ -#ifdef CONFIG_BLOCK -COMPATIBLE_IOCTL(BLKTRACESTART) -COMPATIBLE_IOCTL(BLKTRACESTOP) -COMPATIBLE_IOCTL(BLKTRACESETUP) -COMPATIBLE_IOCTL(BLKTRACETEARDOWN) -#endif /* RAID */ COMPATIBLE_IOCTL(RAID_VERSION) COMPATIBLE_IOCTL(GET_ARRAY_INFO) diff --git a/include/linux/blktrace_api.h b/include/linux/blktrace_api.h index 7b5d56b82b59..972093bf1853 100644 --- a/include/linux/blktrace_api.h +++ b/include/linux/blktrace_api.h @@ -142,10 +142,14 @@ struct blk_user_trace_setup { u32 pid; }; +#ifdef __KERNEL__ #if defined(CONFIG_BLK_DEV_IO_TRACE) extern int blk_trace_ioctl(struct block_device *, unsigned, char __user *); extern void blk_trace_shutdown(struct request_queue *); extern void __blk_add_trace(struct blk_trace *, sector_t, int, int, u32, int, int, void *); +extern int do_blk_trace_setup(struct request_queue *q, + struct block_device *bdev, struct blk_user_trace_setup *buts); + /** * blk_add_trace_rq - Add a trace for a request oriented action @@ -286,6 +290,7 @@ static inline void blk_add_trace_remap(struct request_queue *q, struct bio *bio, #define blk_add_trace_generic(q, rq, rw, what) do { } while (0) #define blk_add_trace_pdu_int(q, what, bio, pdu) do { } while (0) #define blk_add_trace_remap(q, bio, dev, f, t) do {} while (0) +#define do_blk_trace_setup(q, bdev, buts) do {} while (0) #endif /* CONFIG_BLK_DEV_IO_TRACE */ - +#endif /* __KERNEL__ */ #endif From 9617db085c119879cd371e3212806a15596e121a Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 9 Oct 2007 13:23:55 +0200 Subject: [PATCH 33/37] compat_ioctl: move hdio calls to block/compat_ioctl.c These are common to multiple block drivers, so they should be handled by the block layer. Signed-off-by: Arnd Bergmann Signed-off-by: Jens Axboe --- block/compat_ioctl.c | 70 ++++++++++++++++++++++++++++++++++++++++++++ fs/compat_ioctl.c | 60 ------------------------------------- 2 files changed, 70 insertions(+), 60 deletions(-) diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c index 219b7e76e8ad..5c6dafaad938 100644 --- a/block/compat_ioctl.c +++ b/block/compat_ioctl.c @@ -36,6 +36,62 @@ static int compat_put_u64(unsigned long arg, u64 val) return put_user(val, (compat_u64 __user *)compat_ptr(arg)); } +struct compat_hd_geometry { + unsigned char heads; + unsigned char sectors; + unsigned short cylinders; + u32 start; +}; + +static int compat_hdio_getgeo(struct gendisk *disk, struct block_device *bdev, + struct compat_hd_geometry __user *ugeo) +{ + struct hd_geometry geo; + int ret; + + if (!ugeo) + return -EINVAL; + if (!disk->fops->getgeo) + return -ENOTTY; + + /* + * We need to set the startsect first, the driver may + * want to override it. + */ + geo.start = get_start_sect(bdev); + ret = disk->fops->getgeo(bdev, &geo); + if (ret) + return ret; + + ret = copy_to_user(ugeo, &geo, 4); + ret |= __put_user(geo.start, &ugeo->start); + if (ret) + ret = -EFAULT; + + return ret; +} + +static int compat_hdio_ioctl(struct inode *inode, struct file *file, + struct gendisk *disk, unsigned int cmd, unsigned long arg) +{ + mm_segment_t old_fs = get_fs(); + unsigned long kval; + unsigned int __user *uvp; + int error; + + set_fs(KERNEL_DS); + error = blkdev_driver_ioctl(inode, file, disk, + cmd, (unsigned long)(&kval)); + set_fs(old_fs); + + if (error == 0) { + uvp = compat_ptr(arg); + if (put_user(kval, uvp)) + error = -EFAULT; + } + return error; +} + #define BLKBSZGET_32 _IOR(0x12, 112, int) #define BLKBSZSET_32 _IOW(0x12, 113, int) #define BLKGETSIZE64_32 _IOR(0x12, 114, int) @@ -93,6 +149,18 @@ static int compat_blkdev_driver_ioctl(struct inode *inode, struct file *file, int ret; switch (arg) { + case HDIO_GET_UNMASKINTR: + case HDIO_GET_MULTCOUNT: + case HDIO_GET_KEEPSETTINGS: + case HDIO_GET_32BIT: + case HDIO_GET_NOWERR: + case HDIO_GET_DMA: + case HDIO_GET_NICE: + case HDIO_GET_WCACHE: + case HDIO_GET_ACOUSTIC: + case HDIO_GET_ADDRESS: + case HDIO_GET_BUSSTATE: + return compat_hdio_ioctl(inode, file, disk, cmd, arg); /* * No handler required for the ones below, we just need to * convert arg to a 64 bit pointer. @@ -266,6 +334,8 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg) struct gendisk *disk = bdev->bd_disk; switch (cmd) { + case HDIO_GETGEO: + return compat_hdio_getgeo(disk, bdev, compat_ptr(arg)); case BLKFLSBUF: case BLKROSET: /* diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 71065603a581..e6a94714b1b0 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -667,53 +666,6 @@ out: #endif #ifdef CONFIG_BLOCK -struct hd_geometry32 { - unsigned char heads; - unsigned char sectors; - unsigned short cylinders; - u32 start; -}; - -static int hdio_getgeo(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs = get_fs(); - struct hd_geometry geo; - struct hd_geometry32 __user *ugeo; - int err; - - set_fs (KERNEL_DS); - err = sys_ioctl(fd, HDIO_GETGEO, (unsigned long)&geo); - set_fs (old_fs); - ugeo = compat_ptr(arg); - if (!err) { - err = copy_to_user (ugeo, &geo, 4); - err |= __put_user (geo.start, &ugeo->start); - if (err) - err = -EFAULT; - } - return err; -} - -static int hdio_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs = get_fs(); - unsigned long kval; - unsigned int __user *uvp; - int error; - - set_fs(KERNEL_DS); - error = sys_ioctl(fd, cmd, (long)&kval); - set_fs(old_fs); - - if(error == 0) { - uvp = compat_ptr(arg); - if(put_user(kval, uvp)) - error = -EFAULT; - } - return error; -} - - typedef struct sg_io_hdr32 { compat_int_t interface_id; /* [i] 'S' for SCSI generic (required) */ compat_int_t dxfer_direction; /* [i] data transfer direction */ @@ -3208,19 +3160,7 @@ HANDLE_IOCTL(SIOCGSTAMP, do_siocgstamp) HANDLE_IOCTL(SIOCGSTAMPNS, do_siocgstampns) #endif #ifdef CONFIG_BLOCK -HANDLE_IOCTL(HDIO_GETGEO, hdio_getgeo) HANDLE_IOCTL(BLKPG, blkpg_ioctl_trans) -HANDLE_IOCTL(HDIO_GET_UNMASKINTR, hdio_ioctl_trans) -HANDLE_IOCTL(HDIO_GET_MULTCOUNT, hdio_ioctl_trans) -HANDLE_IOCTL(HDIO_GET_KEEPSETTINGS, hdio_ioctl_trans) -HANDLE_IOCTL(HDIO_GET_32BIT, hdio_ioctl_trans) -HANDLE_IOCTL(HDIO_GET_NOWERR, hdio_ioctl_trans) -HANDLE_IOCTL(HDIO_GET_DMA, hdio_ioctl_trans) -HANDLE_IOCTL(HDIO_GET_NICE, hdio_ioctl_trans) -HANDLE_IOCTL(HDIO_GET_WCACHE, hdio_ioctl_trans) -HANDLE_IOCTL(HDIO_GET_ACOUSTIC, hdio_ioctl_trans) -HANDLE_IOCTL(HDIO_GET_ADDRESS, hdio_ioctl_trans) -HANDLE_IOCTL(HDIO_GET_BUSSTATE, hdio_ioctl_trans) HANDLE_IOCTL(FDSETPRM32, fd_ioctl_trans) HANDLE_IOCTL(FDDEFPRM32, fd_ioctl_trans) HANDLE_IOCTL(FDGETPRM32, fd_ioctl_trans) From 18cf7f8723d913ce02bea43e468bebdd07bc880c Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 9 Oct 2007 13:23:56 +0200 Subject: [PATCH 34/37] compat_ioctl: move BLKPG handling to block/compat_ioctl.c BLKPG is common to all block devices, so it should be handled by common code. Signed-off-by: Arnd Bergmann Signed-off-by: Jens Axboe --- block/compat_ioctl.c | 31 +++++++++++++++++++++++++++++++ fs/compat_ioctl.c | 33 --------------------------------- 2 files changed, 31 insertions(+), 33 deletions(-) diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c index 5c6dafaad938..44807d38b1e7 100644 --- a/block/compat_ioctl.c +++ b/block/compat_ioctl.c @@ -92,6 +92,35 @@ static int compat_hdio_ioctl(struct inode *inode, struct file *file, return error; } +struct compat_blkpg_ioctl_arg { + compat_int_t op; + compat_int_t flags; + compat_int_t datalen; + compat_caddr_t data; +}; + +static int compat_blkpg_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, struct compat_blkpg_ioctl_arg __user *ua32) +{ + struct blkpg_ioctl_arg __user *a = compat_alloc_user_space(sizeof(*a)); + compat_caddr_t udata; + compat_int_t n; + int err; + + err = get_user(n, &ua32->op); + err |= put_user(n, &a->op); + err |= get_user(n, &ua32->flags); + err |= put_user(n, &a->flags); + err |= get_user(n, &ua32->datalen); + err |= put_user(n, &a->datalen); + err |= get_user(udata, &ua32->data); + err |= put_user(compat_ptr(udata), &a->data); + if (err) + return err; + + return blkdev_ioctl(inode, file, cmd, (unsigned long)a); +} + #define BLKBSZGET_32 _IOR(0x12, 112, int) #define BLKBSZSET_32 _IOW(0x12, 113, int) #define BLKGETSIZE64_32 _IOR(0x12, 114, int) @@ -348,6 +377,8 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg) case BLKBSZSET_32: return blkdev_ioctl(inode, file, BLKBSZSET, (unsigned long)compat_ptr(arg)); + case BLKPG: + return compat_blkpg_ioctl(inode, file, cmd, compat_ptr(arg)); } lock_kernel(); diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index e6a94714b1b0..3baa90d31090 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -47,7 +47,6 @@ #include #include #include -#include #include #include #include @@ -1487,37 +1486,6 @@ ret_einval(unsigned int fd, unsigned int cmd, unsigned long arg) return -EINVAL; } -#ifdef CONFIG_BLOCK -struct blkpg_ioctl_arg32 { - compat_int_t op; - compat_int_t flags; - compat_int_t datalen; - compat_caddr_t data; -}; - -static int blkpg_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct blkpg_ioctl_arg32 __user *ua32 = compat_ptr(arg); - struct blkpg_ioctl_arg __user *a = compat_alloc_user_space(sizeof(*a)); - compat_caddr_t udata; - compat_int_t n; - int err; - - err = get_user(n, &ua32->op); - err |= put_user(n, &a->op); - err |= get_user(n, &ua32->flags); - err |= put_user(n, &a->flags); - err |= get_user(n, &ua32->datalen); - err |= put_user(n, &a->datalen); - err |= get_user(udata, &ua32->data); - err |= put_user(compat_ptr(udata), &a->data); - if (err) - return err; - - return sys_ioctl(fd, cmd, (unsigned long)a); -} -#endif - static int ioc_settimeout(unsigned int fd, unsigned int cmd, unsigned long arg) { return rw_long(fd, AUTOFS_IOC_SETTIMEOUT, arg); @@ -3160,7 +3128,6 @@ HANDLE_IOCTL(SIOCGSTAMP, do_siocgstamp) HANDLE_IOCTL(SIOCGSTAMPNS, do_siocgstampns) #endif #ifdef CONFIG_BLOCK -HANDLE_IOCTL(BLKPG, blkpg_ioctl_trans) HANDLE_IOCTL(FDSETPRM32, fd_ioctl_trans) HANDLE_IOCTL(FDDEFPRM32, fd_ioctl_trans) HANDLE_IOCTL(FDGETPRM32, fd_ioctl_trans) From b3087cc4f31a66c8c7b63419e913ed9d34145f10 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 9 Oct 2007 13:23:56 +0200 Subject: [PATCH 35/37] compat_ioctl: move cdrom handlers to block/compat_ioctl.c These are shared by all cd-rom drivers and should have common handlers. Do slight cosmetic cleanups in the process. Signed-off-by: Arnd Bergmann Signed-off-by: Jens Axboe --- block/compat_ioctl.c | 83 ++++++++++++++++++++++++++++++++++ fs/compat_ioctl.c | 105 ------------------------------------------- 2 files changed, 83 insertions(+), 105 deletions(-) diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c index 44807d38b1e7..92b3e8d07ca6 100644 --- a/block/compat_ioctl.c +++ b/block/compat_ioctl.c @@ -92,6 +92,84 @@ static int compat_hdio_ioctl(struct inode *inode, struct file *file, return error; } +struct compat_cdrom_read_audio { + union cdrom_addr addr; + u8 addr_format; + compat_int_t nframes; + compat_caddr_t buf; +}; + +struct compat_cdrom_generic_command { + unsigned char cmd[CDROM_PACKET_SIZE]; + compat_caddr_t buffer; + compat_uint_t buflen; + compat_int_t stat; + compat_caddr_t sense; + unsigned char data_direction; + compat_int_t quiet; + compat_int_t timeout; + compat_caddr_t reserved[1]; +}; + +static int compat_cdrom_read_audio(struct inode *inode, struct file *file, + struct gendisk *disk, unsigned int cmd, unsigned long arg) +{ + struct cdrom_read_audio __user *cdread_audio; + struct compat_cdrom_read_audio __user *cdread_audio32; + __u32 data; + void __user *datap; + + cdread_audio = compat_alloc_user_space(sizeof(*cdread_audio)); + cdread_audio32 = compat_ptr(arg); + + if (copy_in_user(&cdread_audio->addr, + &cdread_audio32->addr, + (sizeof(*cdread_audio32) - + sizeof(compat_caddr_t)))) + return -EFAULT; + + if (get_user(data, &cdread_audio32->buf)) + return -EFAULT; + datap = compat_ptr(data); + if (put_user(datap, &cdread_audio->buf)) + return -EFAULT; + + return blkdev_driver_ioctl(inode, file, disk, cmd, + (unsigned long)cdread_audio); +} + +static int compat_cdrom_generic_command(struct inode *inode, struct file *file, + struct gendisk *disk, unsigned int cmd, unsigned long arg) +{ + struct cdrom_generic_command __user *cgc; + struct compat_cdrom_generic_command __user *cgc32; + u32 data; + unsigned char dir; + int itmp; + + cgc = compat_alloc_user_space(sizeof(*cgc)); + cgc32 = compat_ptr(arg); + + if (copy_in_user(&cgc->cmd, &cgc32->cmd, sizeof(cgc->cmd)) || + get_user(data, &cgc32->buffer) || + put_user(compat_ptr(data), &cgc->buffer) || + copy_in_user(&cgc->buflen, &cgc32->buflen, + (sizeof(unsigned int) + sizeof(int))) || + get_user(data, &cgc32->sense) || + put_user(compat_ptr(data), &cgc->sense) || + get_user(dir, &cgc32->data_direction) || + put_user(dir, &cgc->data_direction) || + get_user(itmp, &cgc32->quiet) || + put_user(itmp, &cgc->quiet) || + get_user(itmp, &cgc32->timeout) || + put_user(itmp, &cgc->timeout) || + get_user(data, &cgc32->reserved[0]) || + put_user(compat_ptr(data), &cgc->reserved[0])) + return -EFAULT; + + return blkdev_driver_ioctl(inode, file, disk, cmd, (unsigned long)cgc); +} + struct compat_blkpg_ioctl_arg { compat_int_t op; compat_int_t flags; @@ -190,6 +268,11 @@ static int compat_blkdev_driver_ioctl(struct inode *inode, struct file *file, case HDIO_GET_ADDRESS: case HDIO_GET_BUSSTATE: return compat_hdio_ioctl(inode, file, disk, cmd, arg); + case CDROMREADAUDIO: + return compat_cdrom_read_audio(inode, file, disk, cmd, arg); + case CDROM_SEND_PACKET: + return compat_cdrom_generic_command(inode, file, disk, cmd, arg); + /* * No handler required for the ones below, we just need to * convert arg to a 64 bit pointer. diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 3baa90d31090..24c743571127 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -37,7 +37,6 @@ #include #include #include -#include #include #include #include @@ -1039,108 +1038,6 @@ static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) return err ? -EFAULT: 0; } -struct cdrom_read_audio32 { - union cdrom_addr addr; - u8 addr_format; - compat_int_t nframes; - compat_caddr_t buf; -}; - -struct cdrom_generic_command32 { - unsigned char cmd[CDROM_PACKET_SIZE]; - compat_caddr_t buffer; - compat_uint_t buflen; - compat_int_t stat; - compat_caddr_t sense; - unsigned char data_direction; - compat_int_t quiet; - compat_int_t timeout; - compat_caddr_t reserved[1]; -}; - -static int cdrom_do_read_audio(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct cdrom_read_audio __user *cdread_audio; - struct cdrom_read_audio32 __user *cdread_audio32; - __u32 data; - void __user *datap; - - cdread_audio = compat_alloc_user_space(sizeof(*cdread_audio)); - cdread_audio32 = compat_ptr(arg); - - if (copy_in_user(&cdread_audio->addr, - &cdread_audio32->addr, - (sizeof(*cdread_audio32) - - sizeof(compat_caddr_t)))) - return -EFAULT; - - if (get_user(data, &cdread_audio32->buf)) - return -EFAULT; - datap = compat_ptr(data); - if (put_user(datap, &cdread_audio->buf)) - return -EFAULT; - - return sys_ioctl(fd, cmd, (unsigned long) cdread_audio); -} - -static int cdrom_do_generic_command(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct cdrom_generic_command __user *cgc; - struct cdrom_generic_command32 __user *cgc32; - u32 data; - unsigned char dir; - int itmp; - - cgc = compat_alloc_user_space(sizeof(*cgc)); - cgc32 = compat_ptr(arg); - - if (copy_in_user(&cgc->cmd, &cgc32->cmd, sizeof(cgc->cmd)) || - get_user(data, &cgc32->buffer) || - put_user(compat_ptr(data), &cgc->buffer) || - copy_in_user(&cgc->buflen, &cgc32->buflen, - (sizeof(unsigned int) + sizeof(int))) || - get_user(data, &cgc32->sense) || - put_user(compat_ptr(data), &cgc->sense) || - get_user(dir, &cgc32->data_direction) || - put_user(dir, &cgc->data_direction) || - get_user(itmp, &cgc32->quiet) || - put_user(itmp, &cgc->quiet) || - get_user(itmp, &cgc32->timeout) || - put_user(itmp, &cgc->timeout) || - get_user(data, &cgc32->reserved[0]) || - put_user(compat_ptr(data), &cgc->reserved[0])) - return -EFAULT; - - return sys_ioctl(fd, cmd, (unsigned long) cgc); -} - -static int cdrom_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - int err; - - switch(cmd) { - case CDROMREADAUDIO: - err = cdrom_do_read_audio(fd, cmd, arg); - break; - - case CDROM_SEND_PACKET: - err = cdrom_do_generic_command(fd, cmd, arg); - break; - - default: - do { - static int count; - if (++count <= 20) - printk("cdrom_ioctl: Unknown cmd fd(%d) " - "cmd(%08x) arg(%08x)\n", - (int)fd, (unsigned int)cmd, (unsigned int)arg); - } while(0); - err = -EINVAL; - break; - }; - - return err; -} #endif /* CONFIG_BLOCK */ #ifdef CONFIG_VT @@ -3147,8 +3044,6 @@ HANDLE_IOCTL(PPPIOCSACTIVE32, ppp_sock_fprog_ioctl_trans) #ifdef CONFIG_BLOCK HANDLE_IOCTL(MTIOCGET32, mt_ioctl_trans) HANDLE_IOCTL(MTIOCPOS32, mt_ioctl_trans) -HANDLE_IOCTL(CDROMREADAUDIO, cdrom_ioctl_trans) -HANDLE_IOCTL(CDROM_SEND_PACKET, cdrom_ioctl_trans) #endif #define AUTOFS_IOC_SETTIMEOUT32 _IOWR(0x93,0x64,unsigned int) HANDLE_IOCTL(AUTOFS_IOC_SETTIMEOUT32, ioc_settimeout) From 1ca91cd0336b05b91c51b403c9ed9d297813533f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 9 Oct 2007 13:23:57 +0200 Subject: [PATCH 36/37] compat_ioctl: move floppy handlers to block/compat_ioctl.c The floppy ioctls are used by multiple drivers, so they should be handled in a shared location. Also, add minor cleanups. Signed-off-by: Arnd Bergmann Signed-off-by: Jens Axboe --- block/compat_ioctl.c | 336 ++++++++++++++++++++++++++++++++++++++++++ fs/compat_ioctl.c | 337 ------------------------------------------- 2 files changed, 336 insertions(+), 337 deletions(-) diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c index 92b3e8d07ca6..f84093b97f70 100644 --- a/block/compat_ioctl.c +++ b/block/compat_ioctl.c @@ -203,6 +203,332 @@ static int compat_blkpg_ioctl(struct inode *inode, struct file *file, #define BLKBSZSET_32 _IOW(0x12, 113, int) #define BLKGETSIZE64_32 _IOR(0x12, 114, int) +struct compat_floppy_struct { + compat_uint_t size; + compat_uint_t sect; + compat_uint_t head; + compat_uint_t track; + compat_uint_t stretch; + unsigned char gap; + unsigned char rate; + unsigned char spec1; + unsigned char fmt_gap; + const compat_caddr_t name; +}; + +struct compat_floppy_drive_params { + char cmos; + compat_ulong_t max_dtr; + compat_ulong_t hlt; + compat_ulong_t hut; + compat_ulong_t srt; + compat_ulong_t spinup; + compat_ulong_t spindown; + unsigned char spindown_offset; + unsigned char select_delay; + unsigned char rps; + unsigned char tracks; + compat_ulong_t timeout; + unsigned char interleave_sect; + struct floppy_max_errors max_errors; + char flags; + char read_track; + short autodetect[8]; + compat_int_t checkfreq; + compat_int_t native_format; +}; + +struct compat_floppy_drive_struct { + signed char flags; + compat_ulong_t spinup_date; + compat_ulong_t select_date; + compat_ulong_t first_read_date; + short probed_format; + short track; + short maxblock; + short maxtrack; + compat_int_t generation; + compat_int_t keep_data; + compat_int_t fd_ref; + compat_int_t fd_device; + compat_int_t last_checked; + compat_caddr_t dmabuf; + compat_int_t bufblocks; +}; + +struct compat_floppy_fdc_state { + compat_int_t spec1; + compat_int_t spec2; + compat_int_t dtr; + unsigned char version; + unsigned char dor; + compat_ulong_t address; + unsigned int rawcmd:2; + unsigned int reset:1; + unsigned int need_configure:1; + unsigned int perp_mode:2; + unsigned int has_fifo:1; + unsigned int driver_version; + unsigned char track[4]; +}; + +struct compat_floppy_write_errors { + unsigned int write_errors; + compat_ulong_t first_error_sector; + compat_int_t first_error_generation; + compat_ulong_t last_error_sector; + compat_int_t last_error_generation; + compat_uint_t badness; +}; + +#define FDSETPRM32 _IOW(2, 0x42, struct compat_floppy_struct) +#define FDDEFPRM32 _IOW(2, 0x43, struct compat_floppy_struct) +#define FDGETPRM32 _IOR(2, 0x04, struct compat_floppy_struct) +#define FDSETDRVPRM32 _IOW(2, 0x90, struct compat_floppy_drive_params) +#define FDGETDRVPRM32 _IOR(2, 0x11, struct compat_floppy_drive_params) +#define FDGETDRVSTAT32 _IOR(2, 0x12, struct compat_floppy_drive_struct) +#define FDPOLLDRVSTAT32 _IOR(2, 0x13, struct compat_floppy_drive_struct) +#define FDGETFDCSTAT32 _IOR(2, 0x15, struct compat_floppy_fdc_state) +#define FDWERRORGET32 _IOR(2, 0x17, struct compat_floppy_write_errors) + +static struct { + unsigned int cmd32; + unsigned int cmd; +} fd_ioctl_trans_table[] = { + { FDSETPRM32, FDSETPRM }, + { FDDEFPRM32, FDDEFPRM }, + { FDGETPRM32, FDGETPRM }, + { FDSETDRVPRM32, FDSETDRVPRM }, + { FDGETDRVPRM32, FDGETDRVPRM }, + { FDGETDRVSTAT32, FDGETDRVSTAT }, + { FDPOLLDRVSTAT32, FDPOLLDRVSTAT }, + { FDGETFDCSTAT32, FDGETFDCSTAT }, + { FDWERRORGET32, FDWERRORGET } +}; + +#define NR_FD_IOCTL_TRANS ARRAY_SIZE(fd_ioctl_trans_table) + +static int compat_fd_ioctl(struct inode *inode, struct file *file, + struct gendisk *disk, unsigned int cmd, unsigned long arg) +{ + mm_segment_t old_fs = get_fs(); + void *karg = NULL; + unsigned int kcmd = 0; + int i, err; + + for (i = 0; i < NR_FD_IOCTL_TRANS; i++) + if (cmd == fd_ioctl_trans_table[i].cmd32) { + kcmd = fd_ioctl_trans_table[i].cmd; + break; + } + if (!kcmd) + return -EINVAL; + + switch (cmd) { + case FDSETPRM32: + case FDDEFPRM32: + case FDGETPRM32: + { + compat_uptr_t name; + struct compat_floppy_struct __user *uf; + struct floppy_struct *f; + + uf = compat_ptr(arg); + f = karg = kmalloc(sizeof(struct floppy_struct), GFP_KERNEL); + if (!karg) + return -ENOMEM; + if (cmd == FDGETPRM32) + break; + err = __get_user(f->size, &uf->size); + err |= __get_user(f->sect, &uf->sect); + err |= __get_user(f->head, &uf->head); + err |= __get_user(f->track, &uf->track); + err |= __get_user(f->stretch, &uf->stretch); + err |= __get_user(f->gap, &uf->gap); + err |= __get_user(f->rate, &uf->rate); + err |= __get_user(f->spec1, &uf->spec1); + err |= __get_user(f->fmt_gap, &uf->fmt_gap); + err |= __get_user(name, &uf->name); + f->name = compat_ptr(name); + if (err) { + err = -EFAULT; + goto out; + } + break; + } + case FDSETDRVPRM32: + case FDGETDRVPRM32: + { + struct compat_floppy_drive_params __user *uf; + struct floppy_drive_params *f; + + uf = compat_ptr(arg); + f = karg = kmalloc(sizeof(struct floppy_drive_params), GFP_KERNEL); + if (!karg) + return -ENOMEM; + if (cmd == FDGETDRVPRM32) + break; + err = __get_user(f->cmos, &uf->cmos); + err |= __get_user(f->max_dtr, &uf->max_dtr); + err |= __get_user(f->hlt, &uf->hlt); + err |= __get_user(f->hut, &uf->hut); + err |= __get_user(f->srt, &uf->srt); + err |= __get_user(f->spinup, &uf->spinup); + err |= __get_user(f->spindown, &uf->spindown); + err |= __get_user(f->spindown_offset, &uf->spindown_offset); + err |= __get_user(f->select_delay, &uf->select_delay); + err |= __get_user(f->rps, &uf->rps); + err |= __get_user(f->tracks, &uf->tracks); + err |= __get_user(f->timeout, &uf->timeout); + err |= __get_user(f->interleave_sect, &uf->interleave_sect); + err |= __copy_from_user(&f->max_errors, &uf->max_errors, sizeof(f->max_errors)); + err |= __get_user(f->flags, &uf->flags); + err |= __get_user(f->read_track, &uf->read_track); + err |= __copy_from_user(f->autodetect, uf->autodetect, sizeof(f->autodetect)); + err |= __get_user(f->checkfreq, &uf->checkfreq); + err |= __get_user(f->native_format, &uf->native_format); + if (err) { + err = -EFAULT; + goto out; + } + break; + } + case FDGETDRVSTAT32: + case FDPOLLDRVSTAT32: + karg = kmalloc(sizeof(struct floppy_drive_struct), GFP_KERNEL); + if (!karg) + return -ENOMEM; + break; + case FDGETFDCSTAT32: + karg = kmalloc(sizeof(struct floppy_fdc_state), GFP_KERNEL); + if (!karg) + return -ENOMEM; + break; + case FDWERRORGET32: + karg = kmalloc(sizeof(struct floppy_write_errors), GFP_KERNEL); + if (!karg) + return -ENOMEM; + break; + default: + return -EINVAL; + } + set_fs(KERNEL_DS); + err = blkdev_driver_ioctl(inode, file, disk, kcmd, (unsigned long)karg); + set_fs(old_fs); + if (err) + goto out; + switch (cmd) { + case FDGETPRM32: + { + struct floppy_struct *f = karg; + struct compat_floppy_struct __user *uf = compat_ptr(arg); + + err = __put_user(f->size, &uf->size); + err |= __put_user(f->sect, &uf->sect); + err |= __put_user(f->head, &uf->head); + err |= __put_user(f->track, &uf->track); + err |= __put_user(f->stretch, &uf->stretch); + err |= __put_user(f->gap, &uf->gap); + err |= __put_user(f->rate, &uf->rate); + err |= __put_user(f->spec1, &uf->spec1); + err |= __put_user(f->fmt_gap, &uf->fmt_gap); + err |= __put_user((u64)f->name, (compat_caddr_t __user *)&uf->name); + break; + } + case FDGETDRVPRM32: + { + struct compat_floppy_drive_params __user *uf; + struct floppy_drive_params *f = karg; + + uf = compat_ptr(arg); + err = __put_user(f->cmos, &uf->cmos); + err |= __put_user(f->max_dtr, &uf->max_dtr); + err |= __put_user(f->hlt, &uf->hlt); + err |= __put_user(f->hut, &uf->hut); + err |= __put_user(f->srt, &uf->srt); + err |= __put_user(f->spinup, &uf->spinup); + err |= __put_user(f->spindown, &uf->spindown); + err |= __put_user(f->spindown_offset, &uf->spindown_offset); + err |= __put_user(f->select_delay, &uf->select_delay); + err |= __put_user(f->rps, &uf->rps); + err |= __put_user(f->tracks, &uf->tracks); + err |= __put_user(f->timeout, &uf->timeout); + err |= __put_user(f->interleave_sect, &uf->interleave_sect); + err |= __copy_to_user(&uf->max_errors, &f->max_errors, sizeof(f->max_errors)); + err |= __put_user(f->flags, &uf->flags); + err |= __put_user(f->read_track, &uf->read_track); + err |= __copy_to_user(uf->autodetect, f->autodetect, sizeof(f->autodetect)); + err |= __put_user(f->checkfreq, &uf->checkfreq); + err |= __put_user(f->native_format, &uf->native_format); + break; + } + case FDGETDRVSTAT32: + case FDPOLLDRVSTAT32: + { + struct compat_floppy_drive_struct __user *uf; + struct floppy_drive_struct *f = karg; + + uf = compat_ptr(arg); + err = __put_user(f->flags, &uf->flags); + err |= __put_user(f->spinup_date, &uf->spinup_date); + err |= __put_user(f->select_date, &uf->select_date); + err |= __put_user(f->first_read_date, &uf->first_read_date); + err |= __put_user(f->probed_format, &uf->probed_format); + err |= __put_user(f->track, &uf->track); + err |= __put_user(f->maxblock, &uf->maxblock); + err |= __put_user(f->maxtrack, &uf->maxtrack); + err |= __put_user(f->generation, &uf->generation); + err |= __put_user(f->keep_data, &uf->keep_data); + err |= __put_user(f->fd_ref, &uf->fd_ref); + err |= __put_user(f->fd_device, &uf->fd_device); + err |= __put_user(f->last_checked, &uf->last_checked); + err |= __put_user((u64)f->dmabuf, &uf->dmabuf); + err |= __put_user((u64)f->bufblocks, &uf->bufblocks); + break; + } + case FDGETFDCSTAT32: + { + struct compat_floppy_fdc_state __user *uf; + struct floppy_fdc_state *f = karg; + + uf = compat_ptr(arg); + err = __put_user(f->spec1, &uf->spec1); + err |= __put_user(f->spec2, &uf->spec2); + err |= __put_user(f->dtr, &uf->dtr); + err |= __put_user(f->version, &uf->version); + err |= __put_user(f->dor, &uf->dor); + err |= __put_user(f->address, &uf->address); + err |= __copy_to_user((char __user *)&uf->address + sizeof(uf->address), + (char *)&f->address + sizeof(f->address), sizeof(int)); + err |= __put_user(f->driver_version, &uf->driver_version); + err |= __copy_to_user(uf->track, f->track, sizeof(f->track)); + break; + } + case FDWERRORGET32: + { + struct compat_floppy_write_errors __user *uf; + struct floppy_write_errors *f = karg; + + uf = compat_ptr(arg); + err = __put_user(f->write_errors, &uf->write_errors); + err |= __put_user(f->first_error_sector, &uf->first_error_sector); + err |= __put_user(f->first_error_generation, &uf->first_error_generation); + err |= __put_user(f->last_error_sector, &uf->last_error_sector); + err |= __put_user(f->last_error_generation, &uf->last_error_generation); + err |= __put_user(f->badness, &uf->badness); + break; + } + default: + break; + } + if (err) + err = -EFAULT; + +out: + kfree(karg); + return err; +} + struct compat_blk_user_trace_setup { char name[32]; u16 act_mask; @@ -268,6 +594,16 @@ static int compat_blkdev_driver_ioctl(struct inode *inode, struct file *file, case HDIO_GET_ADDRESS: case HDIO_GET_BUSSTATE: return compat_hdio_ioctl(inode, file, disk, cmd, arg); + case FDSETPRM32: + case FDDEFPRM32: + case FDGETPRM32: + case FDSETDRVPRM32: + case FDGETDRVPRM32: + case FDGETDRVSTAT32: + case FDPOLLDRVSTAT32: + case FDGETFDCSTAT32: + case FDWERRORGET32: + return compat_fd_ioctl(inode, file, disk, cmd, arg); case CDROMREADAUDIO: return compat_cdrom_read_audio(inode, file, disk, cmd, arg); case CDROM_SEND_PACKET: diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 24c743571127..b9e3357bcc2e 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -1407,333 +1406,6 @@ static int ioc_settimeout(unsigned int fd, unsigned int cmd, unsigned long arg) #define HIDPGETCONNLIST _IOR('H', 210, int) #define HIDPGETCONNINFO _IOR('H', 211, int) -#ifdef CONFIG_BLOCK -struct floppy_struct32 { - compat_uint_t size; - compat_uint_t sect; - compat_uint_t head; - compat_uint_t track; - compat_uint_t stretch; - unsigned char gap; - unsigned char rate; - unsigned char spec1; - unsigned char fmt_gap; - const compat_caddr_t name; -}; - -struct floppy_drive_params32 { - char cmos; - compat_ulong_t max_dtr; - compat_ulong_t hlt; - compat_ulong_t hut; - compat_ulong_t srt; - compat_ulong_t spinup; - compat_ulong_t spindown; - unsigned char spindown_offset; - unsigned char select_delay; - unsigned char rps; - unsigned char tracks; - compat_ulong_t timeout; - unsigned char interleave_sect; - struct floppy_max_errors max_errors; - char flags; - char read_track; - short autodetect[8]; - compat_int_t checkfreq; - compat_int_t native_format; -}; - -struct floppy_drive_struct32 { - signed char flags; - compat_ulong_t spinup_date; - compat_ulong_t select_date; - compat_ulong_t first_read_date; - short probed_format; - short track; - short maxblock; - short maxtrack; - compat_int_t generation; - compat_int_t keep_data; - compat_int_t fd_ref; - compat_int_t fd_device; - compat_int_t last_checked; - compat_caddr_t dmabuf; - compat_int_t bufblocks; -}; - -struct floppy_fdc_state32 { - compat_int_t spec1; - compat_int_t spec2; - compat_int_t dtr; - unsigned char version; - unsigned char dor; - compat_ulong_t address; - unsigned int rawcmd:2; - unsigned int reset:1; - unsigned int need_configure:1; - unsigned int perp_mode:2; - unsigned int has_fifo:1; - unsigned int driver_version; - unsigned char track[4]; -}; - -struct floppy_write_errors32 { - unsigned int write_errors; - compat_ulong_t first_error_sector; - compat_int_t first_error_generation; - compat_ulong_t last_error_sector; - compat_int_t last_error_generation; - compat_uint_t badness; -}; - -#define FDSETPRM32 _IOW(2, 0x42, struct floppy_struct32) -#define FDDEFPRM32 _IOW(2, 0x43, struct floppy_struct32) -#define FDGETPRM32 _IOR(2, 0x04, struct floppy_struct32) -#define FDSETDRVPRM32 _IOW(2, 0x90, struct floppy_drive_params32) -#define FDGETDRVPRM32 _IOR(2, 0x11, struct floppy_drive_params32) -#define FDGETDRVSTAT32 _IOR(2, 0x12, struct floppy_drive_struct32) -#define FDPOLLDRVSTAT32 _IOR(2, 0x13, struct floppy_drive_struct32) -#define FDGETFDCSTAT32 _IOR(2, 0x15, struct floppy_fdc_state32) -#define FDWERRORGET32 _IOR(2, 0x17, struct floppy_write_errors32) - -static struct { - unsigned int cmd32; - unsigned int cmd; -} fd_ioctl_trans_table[] = { - { FDSETPRM32, FDSETPRM }, - { FDDEFPRM32, FDDEFPRM }, - { FDGETPRM32, FDGETPRM }, - { FDSETDRVPRM32, FDSETDRVPRM }, - { FDGETDRVPRM32, FDGETDRVPRM }, - { FDGETDRVSTAT32, FDGETDRVSTAT }, - { FDPOLLDRVSTAT32, FDPOLLDRVSTAT }, - { FDGETFDCSTAT32, FDGETFDCSTAT }, - { FDWERRORGET32, FDWERRORGET } -}; - -#define NR_FD_IOCTL_TRANS ARRAY_SIZE(fd_ioctl_trans_table) - -static int fd_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs = get_fs(); - void *karg = NULL; - unsigned int kcmd = 0; - int i, err; - - for (i = 0; i < NR_FD_IOCTL_TRANS; i++) - if (cmd == fd_ioctl_trans_table[i].cmd32) { - kcmd = fd_ioctl_trans_table[i].cmd; - break; - } - if (!kcmd) - return -EINVAL; - - switch (cmd) { - case FDSETPRM32: - case FDDEFPRM32: - case FDGETPRM32: - { - compat_uptr_t name; - struct floppy_struct32 __user *uf; - struct floppy_struct *f; - - uf = compat_ptr(arg); - f = karg = kmalloc(sizeof(struct floppy_struct), GFP_KERNEL); - if (!karg) - return -ENOMEM; - if (cmd == FDGETPRM32) - break; - err = __get_user(f->size, &uf->size); - err |= __get_user(f->sect, &uf->sect); - err |= __get_user(f->head, &uf->head); - err |= __get_user(f->track, &uf->track); - err |= __get_user(f->stretch, &uf->stretch); - err |= __get_user(f->gap, &uf->gap); - err |= __get_user(f->rate, &uf->rate); - err |= __get_user(f->spec1, &uf->spec1); - err |= __get_user(f->fmt_gap, &uf->fmt_gap); - err |= __get_user(name, &uf->name); - f->name = compat_ptr(name); - if (err) { - err = -EFAULT; - goto out; - } - break; - } - case FDSETDRVPRM32: - case FDGETDRVPRM32: - { - struct floppy_drive_params32 __user *uf; - struct floppy_drive_params *f; - - uf = compat_ptr(arg); - f = karg = kmalloc(sizeof(struct floppy_drive_params), GFP_KERNEL); - if (!karg) - return -ENOMEM; - if (cmd == FDGETDRVPRM32) - break; - err = __get_user(f->cmos, &uf->cmos); - err |= __get_user(f->max_dtr, &uf->max_dtr); - err |= __get_user(f->hlt, &uf->hlt); - err |= __get_user(f->hut, &uf->hut); - err |= __get_user(f->srt, &uf->srt); - err |= __get_user(f->spinup, &uf->spinup); - err |= __get_user(f->spindown, &uf->spindown); - err |= __get_user(f->spindown_offset, &uf->spindown_offset); - err |= __get_user(f->select_delay, &uf->select_delay); - err |= __get_user(f->rps, &uf->rps); - err |= __get_user(f->tracks, &uf->tracks); - err |= __get_user(f->timeout, &uf->timeout); - err |= __get_user(f->interleave_sect, &uf->interleave_sect); - err |= __copy_from_user(&f->max_errors, &uf->max_errors, sizeof(f->max_errors)); - err |= __get_user(f->flags, &uf->flags); - err |= __get_user(f->read_track, &uf->read_track); - err |= __copy_from_user(f->autodetect, uf->autodetect, sizeof(f->autodetect)); - err |= __get_user(f->checkfreq, &uf->checkfreq); - err |= __get_user(f->native_format, &uf->native_format); - if (err) { - err = -EFAULT; - goto out; - } - break; - } - case FDGETDRVSTAT32: - case FDPOLLDRVSTAT32: - karg = kmalloc(sizeof(struct floppy_drive_struct), GFP_KERNEL); - if (!karg) - return -ENOMEM; - break; - case FDGETFDCSTAT32: - karg = kmalloc(sizeof(struct floppy_fdc_state), GFP_KERNEL); - if (!karg) - return -ENOMEM; - break; - case FDWERRORGET32: - karg = kmalloc(sizeof(struct floppy_write_errors), GFP_KERNEL); - if (!karg) - return -ENOMEM; - break; - default: - return -EINVAL; - } - set_fs (KERNEL_DS); - err = sys_ioctl (fd, kcmd, (unsigned long)karg); - set_fs (old_fs); - if (err) - goto out; - switch (cmd) { - case FDGETPRM32: - { - struct floppy_struct *f = karg; - struct floppy_struct32 __user *uf = compat_ptr(arg); - - err = __put_user(f->size, &uf->size); - err |= __put_user(f->sect, &uf->sect); - err |= __put_user(f->head, &uf->head); - err |= __put_user(f->track, &uf->track); - err |= __put_user(f->stretch, &uf->stretch); - err |= __put_user(f->gap, &uf->gap); - err |= __put_user(f->rate, &uf->rate); - err |= __put_user(f->spec1, &uf->spec1); - err |= __put_user(f->fmt_gap, &uf->fmt_gap); - err |= __put_user((u64)f->name, (compat_caddr_t __user *)&uf->name); - break; - } - case FDGETDRVPRM32: - { - struct floppy_drive_params32 __user *uf; - struct floppy_drive_params *f = karg; - - uf = compat_ptr(arg); - err = __put_user(f->cmos, &uf->cmos); - err |= __put_user(f->max_dtr, &uf->max_dtr); - err |= __put_user(f->hlt, &uf->hlt); - err |= __put_user(f->hut, &uf->hut); - err |= __put_user(f->srt, &uf->srt); - err |= __put_user(f->spinup, &uf->spinup); - err |= __put_user(f->spindown, &uf->spindown); - err |= __put_user(f->spindown_offset, &uf->spindown_offset); - err |= __put_user(f->select_delay, &uf->select_delay); - err |= __put_user(f->rps, &uf->rps); - err |= __put_user(f->tracks, &uf->tracks); - err |= __put_user(f->timeout, &uf->timeout); - err |= __put_user(f->interleave_sect, &uf->interleave_sect); - err |= __copy_to_user(&uf->max_errors, &f->max_errors, sizeof(f->max_errors)); - err |= __put_user(f->flags, &uf->flags); - err |= __put_user(f->read_track, &uf->read_track); - err |= __copy_to_user(uf->autodetect, f->autodetect, sizeof(f->autodetect)); - err |= __put_user(f->checkfreq, &uf->checkfreq); - err |= __put_user(f->native_format, &uf->native_format); - break; - } - case FDGETDRVSTAT32: - case FDPOLLDRVSTAT32: - { - struct floppy_drive_struct32 __user *uf; - struct floppy_drive_struct *f = karg; - - uf = compat_ptr(arg); - err = __put_user(f->flags, &uf->flags); - err |= __put_user(f->spinup_date, &uf->spinup_date); - err |= __put_user(f->select_date, &uf->select_date); - err |= __put_user(f->first_read_date, &uf->first_read_date); - err |= __put_user(f->probed_format, &uf->probed_format); - err |= __put_user(f->track, &uf->track); - err |= __put_user(f->maxblock, &uf->maxblock); - err |= __put_user(f->maxtrack, &uf->maxtrack); - err |= __put_user(f->generation, &uf->generation); - err |= __put_user(f->keep_data, &uf->keep_data); - err |= __put_user(f->fd_ref, &uf->fd_ref); - err |= __put_user(f->fd_device, &uf->fd_device); - err |= __put_user(f->last_checked, &uf->last_checked); - err |= __put_user((u64)f->dmabuf, &uf->dmabuf); - err |= __put_user((u64)f->bufblocks, &uf->bufblocks); - break; - } - case FDGETFDCSTAT32: - { - struct floppy_fdc_state32 __user *uf; - struct floppy_fdc_state *f = karg; - - uf = compat_ptr(arg); - err = __put_user(f->spec1, &uf->spec1); - err |= __put_user(f->spec2, &uf->spec2); - err |= __put_user(f->dtr, &uf->dtr); - err |= __put_user(f->version, &uf->version); - err |= __put_user(f->dor, &uf->dor); - err |= __put_user(f->address, &uf->address); - err |= __copy_to_user((char __user *)&uf->address + sizeof(uf->address), - (char *)&f->address + sizeof(f->address), sizeof(int)); - err |= __put_user(f->driver_version, &uf->driver_version); - err |= __copy_to_user(uf->track, f->track, sizeof(f->track)); - break; - } - case FDWERRORGET32: - { - struct floppy_write_errors32 __user *uf; - struct floppy_write_errors *f = karg; - - uf = compat_ptr(arg); - err = __put_user(f->write_errors, &uf->write_errors); - err |= __put_user(f->first_error_sector, &uf->first_error_sector); - err |= __put_user(f->first_error_generation, &uf->first_error_generation); - err |= __put_user(f->last_error_sector, &uf->last_error_sector); - err |= __put_user(f->last_error_generation, &uf->last_error_generation); - err |= __put_user(f->badness, &uf->badness); - break; - } - default: - break; - } - if (err) - err = -EFAULT; - -out: - kfree(karg); - return err; -} -#endif - struct mtd_oob_buf32 { u_int32_t start; u_int32_t length; @@ -3025,15 +2697,6 @@ HANDLE_IOCTL(SIOCGSTAMP, do_siocgstamp) HANDLE_IOCTL(SIOCGSTAMPNS, do_siocgstampns) #endif #ifdef CONFIG_BLOCK -HANDLE_IOCTL(FDSETPRM32, fd_ioctl_trans) -HANDLE_IOCTL(FDDEFPRM32, fd_ioctl_trans) -HANDLE_IOCTL(FDGETPRM32, fd_ioctl_trans) -HANDLE_IOCTL(FDSETDRVPRM32, fd_ioctl_trans) -HANDLE_IOCTL(FDGETDRVPRM32, fd_ioctl_trans) -HANDLE_IOCTL(FDGETDRVSTAT32, fd_ioctl_trans) -HANDLE_IOCTL(FDPOLLDRVSTAT32, fd_ioctl_trans) -HANDLE_IOCTL(FDGETFDCSTAT32, fd_ioctl_trans) -HANDLE_IOCTL(FDWERRORGET32, fd_ioctl_trans) HANDLE_IOCTL(SG_IO,sg_ioctl_trans) HANDLE_IOCTL(SG_GET_REQUEST_TABLE, sg_grt_trans) #endif From 780513ecb80ea0934fc6833efc4f5ed9ab4ff9bb Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Thu, 11 Oct 2007 21:26:08 +0200 Subject: [PATCH 37/37] [BLOCK] Fix failing compile with BLK_DEV_IO_TRACE=n I get a compilation error in sglist-arch branch with BLK_DEV_IO_TRACE=n: CC block/compat_ioctl.o /usr0/export/dev/bharrosh/git/pub/linux-2.6-block/block/compat_ioctl.c: In function ?compat_blk_trace_setup?: /usr0/export/dev/bharrosh/git/pub/linux-2.6-block/block/compat_ioctl.c:568: error: expected expression before ?do? make[2]: *** [block/compat_ioctl.o] Error 1 Signed-off-by: Jens Axboe --- include/linux/blktrace_api.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/include/linux/blktrace_api.h b/include/linux/blktrace_api.h index 972093bf1853..2e105a12fe29 100644 --- a/include/linux/blktrace_api.h +++ b/include/linux/blktrace_api.h @@ -290,7 +290,12 @@ static inline void blk_add_trace_remap(struct request_queue *q, struct bio *bio, #define blk_add_trace_generic(q, rq, rw, what) do { } while (0) #define blk_add_trace_pdu_int(q, what, bio, pdu) do { } while (0) #define blk_add_trace_remap(q, bio, dev, f, t) do {} while (0) -#define do_blk_trace_setup(q, bdev, buts) do {} while (0) +static inline int do_blk_trace_setup(struct request_queue *q, + struct block_device *bdev, + struct blk_user_trace_setup *buts) +{ + return 0; +} #endif /* CONFIG_BLK_DEV_IO_TRACE */ #endif /* __KERNEL__ */ #endif