Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.dk/linux-2.6-block
Browse files Browse the repository at this point in the history
* 'for-linus' of git://git.kernel.dk/linux-2.6-block:
  libata: implement drain buffers
  libata: eliminate the home grown dma padding in favour of
  block: clear drain buffer if draining for write command
  block: implement request_queue->dma_drain_needed
  block: add request->raw_data_len
  block: update bio according to DMA alignment padding
  libata: update ATAPI overflow draining
  elevator: make elevator_get() attempt to load the appropriate module
  cfq-iosched: add hlist for browsing parallel to the radix tree
  block: make blk_rq_map_user() clear ->bio if it unmaps it
  fs/block_dev.c: remove #if 0'ed code
  make struct def_blk_aops static
  make blk_settings_init() static
  make blk_ioc_init() static
  make blk-core.c:request_cachep static again
  • Loading branch information
Linus Torvalds committed Feb 19, 2008
2 parents 9ef38ea + fa2fc7f commit f6c4276
Show file tree
Hide file tree
Showing 27 changed files with 191 additions and 567 deletions.
4 changes: 3 additions & 1 deletion block/blk-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ static int __make_request(struct request_queue *q, struct bio *bio);
/*
* For the allocated request tables
*/
struct kmem_cache *request_cachep;
static struct kmem_cache *request_cachep;

/*
* For queue allocation
Expand Down Expand Up @@ -127,6 +127,7 @@ void rq_init(struct request_queue *q, struct request *rq)
rq->nr_hw_segments = 0;
rq->ioprio = 0;
rq->special = NULL;
rq->raw_data_len = 0;
rq->buffer = NULL;
rq->tag = -1;
rq->errors = 0;
Expand Down Expand Up @@ -2015,6 +2016,7 @@ void blk_rq_bio_prep(struct request_queue *q, struct request *rq,
rq->hard_cur_sectors = rq->current_nr_sectors;
rq->hard_nr_sectors = rq->nr_sectors = bio_sectors(bio);
rq->buffer = bio_data(bio);
rq->raw_data_len = bio->bi_size;
rq->data_len = bio->bi_size;

rq->bio = rq->biotail = bio;
Expand Down
37 changes: 16 additions & 21 deletions block/blk-ioc.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,13 @@ static struct kmem_cache *iocontext_cachep;

static void cfq_dtor(struct io_context *ioc)
{
struct cfq_io_context *cic[1];
int r;
if (!hlist_empty(&ioc->cic_list)) {
struct cfq_io_context *cic;

/*
* We don't have a specific key to lookup with, so use the gang
* lookup to just retrieve the first item stored. The cfq exit
* function will iterate the full tree, so any member will do.
*/
r = radix_tree_gang_lookup(&ioc->radix_root, (void **) cic, 0, 1);
if (r > 0)
cic[0]->dtor(ioc);
cic = list_entry(ioc->cic_list.first, struct cfq_io_context,
cic_list);
cic->dtor(ioc);
}
}

/*
Expand Down Expand Up @@ -57,18 +53,16 @@ EXPORT_SYMBOL(put_io_context);

static void cfq_exit(struct io_context *ioc)
{
struct cfq_io_context *cic[1];
int r;

rcu_read_lock();
/*
* See comment for cfq_dtor()
*/
r = radix_tree_gang_lookup(&ioc->radix_root, (void **) cic, 0, 1);
rcu_read_unlock();

if (r > 0)
cic[0]->exit(ioc);
if (!hlist_empty(&ioc->cic_list)) {
struct cfq_io_context *cic;

cic = list_entry(ioc->cic_list.first, struct cfq_io_context,
cic_list);
cic->exit(ioc);
}
rcu_read_unlock();
}

/* Called by the exitting task */
Expand Down Expand Up @@ -105,6 +99,7 @@ struct io_context *alloc_io_context(gfp_t gfp_flags, int node)
ret->nr_batch_requests = 0; /* because this is 0 */
ret->aic = NULL;
INIT_RADIX_TREE(&ret->radix_root, GFP_ATOMIC | __GFP_HIGH);
INIT_HLIST_HEAD(&ret->cic_list);
ret->ioc_data = NULL;
}

Expand Down Expand Up @@ -176,7 +171,7 @@ void copy_io_context(struct io_context **pdst, struct io_context **psrc)
}
EXPORT_SYMBOL(copy_io_context);

int __init blk_ioc_init(void)
static int __init blk_ioc_init(void)
{
iocontext_cachep = kmem_cache_create("blkdev_ioc",
sizeof(struct io_context), 0, SLAB_PANIC, NULL);
Expand Down
20 changes: 20 additions & 0 deletions block/blk-map.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ int blk_rq_append_bio(struct request_queue *q, struct request *rq,
rq->biotail->bi_next = bio;
rq->biotail = bio;

rq->raw_data_len += bio->bi_size;
rq->data_len += bio->bi_size;
}
return 0;
Expand Down Expand Up @@ -139,10 +140,29 @@ int blk_rq_map_user(struct request_queue *q, struct request *rq,
ubuf += ret;
}

/*
* __blk_rq_map_user() copies the buffers if starting address
* or length isn't aligned. As the copied buffer is always
* page aligned, we know that there's enough room for padding.
* Extend the last bio and update rq->data_len accordingly.
*
* On unmap, bio_uncopy_user() will use unmodified
* bio_map_data pointed to by bio->bi_private.
*/
if (len & queue_dma_alignment(q)) {
unsigned int pad_len = (queue_dma_alignment(q) & ~len) + 1;
struct bio *bio = rq->biotail;

bio->bi_io_vec[bio->bi_vcnt - 1].bv_len += pad_len;
bio->bi_size += pad_len;
rq->data_len += pad_len;
}

rq->buffer = rq->data = NULL;
return 0;
unmap_rq:
blk_rq_unmap_user(bio);
rq->bio = NULL;
return ret;
}
EXPORT_SYMBOL(blk_rq_map_user);
Expand Down
6 changes: 5 additions & 1 deletion block/blk-merge.c
Original file line number Diff line number Diff line change
Expand Up @@ -220,14 +220,18 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq,
bvprv = bvec;
} /* segments in rq */

if (q->dma_drain_size) {
if (q->dma_drain_size && q->dma_drain_needed(rq)) {
if (rq->cmd_flags & REQ_RW)
memset(q->dma_drain_buffer, 0, q->dma_drain_size);

sg->page_link &= ~0x02;
sg = sg_next(sg);
sg_set_page(sg, virt_to_page(q->dma_drain_buffer),
q->dma_drain_size,
((unsigned long)q->dma_drain_buffer) &
(PAGE_SIZE - 1));
nsegs++;
rq->data_len += q->dma_drain_size;
}

if (sg)
Expand Down
9 changes: 6 additions & 3 deletions block/blk-settings.c
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,7 @@ EXPORT_SYMBOL(blk_queue_stack_limits);
* blk_queue_dma_drain - Set up a drain buffer for excess dma.
*
* @q: the request queue for the device
* @dma_drain_needed: fn which returns non-zero if drain is necessary
* @buf: physically contiguous buffer
* @size: size of the buffer in bytes
*
Expand All @@ -315,14 +316,16 @@ EXPORT_SYMBOL(blk_queue_stack_limits);
* device can support otherwise there won't be room for the drain
* buffer.
*/
int blk_queue_dma_drain(struct request_queue *q, void *buf,
unsigned int size)
extern int blk_queue_dma_drain(struct request_queue *q,
dma_drain_needed_fn *dma_drain_needed,
void *buf, unsigned int size)
{
if (q->max_hw_segments < 2 || q->max_phys_segments < 2)
return -EINVAL;
/* make room for appending the drain */
--q->max_hw_segments;
--q->max_phys_segments;
q->dma_drain_needed = dma_drain_needed;
q->dma_drain_buffer = buf;
q->dma_drain_size = size;

Expand Down Expand Up @@ -386,7 +389,7 @@ void blk_queue_update_dma_alignment(struct request_queue *q, int mask)
}
EXPORT_SYMBOL(blk_queue_update_dma_alignment);

int __init blk_settings_init(void)
static int __init blk_settings_init(void)
{
blk_max_low_pfn = max_low_pfn - 1;
blk_max_pfn = max_pfn - 1;
Expand Down
8 changes: 4 additions & 4 deletions block/bsg.c
Original file line number Diff line number Diff line change
Expand Up @@ -437,14 +437,14 @@ static int blk_complete_sgv4_hdr_rq(struct request *rq, struct sg_io_v4 *hdr,
}

if (rq->next_rq) {
hdr->dout_resid = rq->data_len;
hdr->din_resid = rq->next_rq->data_len;
hdr->dout_resid = rq->raw_data_len;
hdr->din_resid = rq->next_rq->raw_data_len;
blk_rq_unmap_user(bidi_bio);
blk_put_request(rq->next_rq);
} else if (rq_data_dir(rq) == READ)
hdr->din_resid = rq->data_len;
hdr->din_resid = rq->raw_data_len;
else
hdr->dout_resid = rq->data_len;
hdr->dout_resid = rq->raw_data_len;

/*
* If the request generated a negative error number, return it
Expand Down
38 changes: 12 additions & 26 deletions block/cfq-iosched.c
Original file line number Diff line number Diff line change
Expand Up @@ -1145,38 +1145,19 @@ static void cfq_put_queue(struct cfq_queue *cfqq)
/*
* Call func for each cic attached to this ioc. Returns number of cic's seen.
*/
#define CIC_GANG_NR 16
static unsigned int
call_for_each_cic(struct io_context *ioc,
void (*func)(struct io_context *, struct cfq_io_context *))
{
struct cfq_io_context *cics[CIC_GANG_NR];
unsigned long index = 0;
unsigned int called = 0;
int nr;
struct cfq_io_context *cic;
struct hlist_node *n;
int called = 0;

rcu_read_lock();

do {
int i;

/*
* Perhaps there's a better way - this just gang lookups from
* 0 to the end, restarting after each CIC_GANG_NR from the
* last key + 1.
*/
nr = radix_tree_gang_lookup(&ioc->radix_root, (void **) cics,
index, CIC_GANG_NR);
if (!nr)
break;

called += nr;
index = 1 + (unsigned long) cics[nr - 1]->key;

for (i = 0; i < nr; i++)
func(ioc, cics[i]);
} while (nr == CIC_GANG_NR);

hlist_for_each_entry_rcu(cic, n, &ioc->cic_list, cic_list) {
func(ioc, cic);
called++;
}
rcu_read_unlock();

return called;
Expand All @@ -1190,6 +1171,7 @@ static void cic_free_func(struct io_context *ioc, struct cfq_io_context *cic)

spin_lock_irqsave(&ioc->lock, flags);
radix_tree_delete(&ioc->radix_root, cic->dead_key);
hlist_del_rcu(&cic->cic_list);
spin_unlock_irqrestore(&ioc->lock, flags);

kmem_cache_free(cfq_ioc_pool, cic);
Expand Down Expand Up @@ -1280,6 +1262,7 @@ cfq_alloc_io_context(struct cfq_data *cfqd, gfp_t gfp_mask)
if (cic) {
cic->last_end_request = jiffies;
INIT_LIST_HEAD(&cic->queue_list);
INIT_HLIST_NODE(&cic->cic_list);
cic->dtor = cfq_free_io_context;
cic->exit = cfq_exit_io_context;
elv_ioc_count_inc(ioc_count);
Expand Down Expand Up @@ -1501,6 +1484,7 @@ cfq_drop_dead_cic(struct cfq_data *cfqd, struct io_context *ioc,
rcu_assign_pointer(ioc->ioc_data, NULL);

radix_tree_delete(&ioc->radix_root, (unsigned long) cfqd);
hlist_del_rcu(&cic->cic_list);
spin_unlock_irqrestore(&ioc->lock, flags);

cfq_cic_free(cic);
Expand Down Expand Up @@ -1561,6 +1545,8 @@ static int cfq_cic_link(struct cfq_data *cfqd, struct io_context *ioc,
spin_lock_irqsave(&ioc->lock, flags);
ret = radix_tree_insert(&ioc->radix_root,
(unsigned long) cfqd, cic);
if (!ret)
hlist_add_head_rcu(&cic->cic_list, &ioc->cic_list);
spin_unlock_irqrestore(&ioc->lock, flags);

radix_tree_preload_end();
Expand Down
15 changes: 15 additions & 0 deletions block/elevator.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,21 @@ static struct elevator_type *elevator_get(const char *name)
spin_lock(&elv_list_lock);

e = elevator_find(name);
if (!e) {
char elv[ELV_NAME_MAX + strlen("-iosched")];

spin_unlock(&elv_list_lock);

if (!strcmp(name, "anticipatory"))
sprintf(elv, "as-iosched");
else
sprintf(elv, "%s-iosched", name);

request_module(elv);
spin_lock(&elv_list_lock);
e = elevator_find(name);
}

if (e && !try_module_get(e->elevator_owner))
e = NULL;

Expand Down
3 changes: 2 additions & 1 deletion block/scsi_ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ static int blk_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr,
hdr->info = 0;
if (hdr->masked_status || hdr->host_status || hdr->driver_status)
hdr->info |= SG_INFO_CHECK;
hdr->resid = rq->data_len;
hdr->resid = rq->raw_data_len;
hdr->sb_len_wr = 0;

if (rq->sense_len && hdr->sbp) {
Expand Down Expand Up @@ -528,6 +528,7 @@ static int __blk_send_generic(struct request_queue *q, struct gendisk *bd_disk,
rq = blk_get_request(q, WRITE, __GFP_WAIT);
rq->cmd_type = REQ_TYPE_BLOCK_PC;
rq->data = NULL;
rq->raw_data_len = 0;
rq->data_len = 0;
rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
memset(rq->cmd, 0, sizeof(rq->cmd));
Expand Down
5 changes: 0 additions & 5 deletions drivers/ata/ahci.c
Original file line number Diff line number Diff line change
Expand Up @@ -1975,16 +1975,11 @@ static int ahci_port_start(struct ata_port *ap)
struct ahci_port_priv *pp;
void *mem;
dma_addr_t mem_dma;
int rc;

pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
if (!pp)
return -ENOMEM;

rc = ata_pad_alloc(ap, dev);
if (rc)
return rc;

mem = dmam_alloc_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma,
GFP_KERNEL);
if (!mem)
Expand Down
Loading

0 comments on commit f6c4276

Please sign in to comment.