Commit 6be9f7b2 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'for-linus' of git://git.kernel.dk/linux-2.6-block

* 'for-linus' of git://git.kernel.dk/linux-2.6-block:
  cfq-iosched: fix rcu freeing of cfq io contexts
  Fix bounce setting for 64-bit
parents 8774b7f6 34e6bbf2
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -140,7 +140,7 @@ void blk_queue_bounce_limit(struct request_queue *q, u64 dma_addr)
	/* Assume anything <= 4GB can be handled by IOMMU.
	   Actually some IOMMUs can handle everything, but I don't
	   know of a way to test this here. */
	if (b_pfn <= (min_t(u64, 0xffffffff, BLK_BOUNCE_HIGH) >> PAGE_SHIFT))
	if (b_pfn < (min_t(u64, 0x100000000UL, BLK_BOUNCE_HIGH) >> PAGE_SHIFT))
		dma = 1;
	q->bounce_pfn = max_low_pfn;
#else
+27 −30
Original line number Diff line number Diff line
@@ -1143,24 +1143,37 @@ static void cfq_put_queue(struct cfq_queue *cfqq)
}

/*
 * Call func for each cic attached to this ioc. Returns number of cic's seen.
 * Call func for each cic attached to this ioc.
 */
static unsigned int
static void
call_for_each_cic(struct io_context *ioc,
		  void (*func)(struct io_context *, struct cfq_io_context *))
{
	struct cfq_io_context *cic;
	struct hlist_node *n;
	int called = 0;

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

static void cfq_cic_free_rcu(struct rcu_head *head)
{
	struct cfq_io_context *cic;

	cic = container_of(head, struct cfq_io_context, rcu_head);

	kmem_cache_free(cfq_ioc_pool, cic);
	elv_ioc_count_dec(ioc_count);

	if (ioc_gone && !elv_ioc_count_read(ioc_count))
		complete(ioc_gone);
}

	return called;
static void cfq_cic_free(struct cfq_io_context *cic)
{
	call_rcu(&cic->rcu_head, cfq_cic_free_rcu);
}

static void cic_free_func(struct io_context *ioc, struct cfq_io_context *cic)
@@ -1174,24 +1187,18 @@ static void cic_free_func(struct io_context *ioc, struct cfq_io_context *cic)
	hlist_del_rcu(&cic->cic_list);
	spin_unlock_irqrestore(&ioc->lock, flags);

	kmem_cache_free(cfq_ioc_pool, cic);
	cfq_cic_free(cic);
}

static void cfq_free_io_context(struct io_context *ioc)
{
	int freed;

	/*
	 * ioc->refcount is zero here, so no more cic's are allowed to be
	 * linked into this ioc. So it should be ok to iterate over the known
	 * list, we will see all cic's since no new ones are added.
	 * ioc->refcount is zero here, or we are called from elv_unregister(),
	 * so no more cic's are allowed to be linked into this ioc.  So it
	 * should be ok to iterate over the known list, we will see all cic's
	 * since no new ones are added.
	 */
	freed = call_for_each_cic(ioc, cic_free_func);

	elv_ioc_count_mod(ioc_count, -freed);

	if (ioc_gone && !elv_ioc_count_read(ioc_count))
		complete(ioc_gone);
	call_for_each_cic(ioc, cic_free_func);
}

static void cfq_exit_cfqq(struct cfq_data *cfqd, struct cfq_queue *cfqq)
@@ -1458,15 +1465,6 @@ cfq_get_queue(struct cfq_data *cfqd, int is_sync, struct io_context *ioc,
	return cfqq;
}

static void cfq_cic_free(struct cfq_io_context *cic)
{
	kmem_cache_free(cfq_ioc_pool, cic);
	elv_ioc_count_dec(ioc_count);

	if (ioc_gone && !elv_ioc_count_read(ioc_count))
		complete(ioc_gone);
}

/*
 * We drop cfq io contexts lazily, so we may find a dead one.
 */
@@ -2138,7 +2136,7 @@ static int __init cfq_slab_setup(void)
	if (!cfq_pool)
		goto fail;

	cfq_ioc_pool = KMEM_CACHE(cfq_io_context, SLAB_DESTROY_BY_RCU);
	cfq_ioc_pool = KMEM_CACHE(cfq_io_context, 0);
	if (!cfq_ioc_pool)
		goto fail;

@@ -2286,7 +2284,6 @@ static void __exit cfq_exit(void)
	smp_wmb();
	if (elv_ioc_count_read(ioc_count))
		wait_for_completion(ioc_gone);
	synchronize_rcu();
	cfq_slab_kill();
}

+3 −0
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@
#define IOCONTEXT_H

#include <linux/radix-tree.h>
#include <linux/rcupdate.h>

/*
 * This is the per-process anticipatory I/O scheduler state.
@@ -54,6 +55,8 @@ struct cfq_io_context {

	void (*dtor)(struct io_context *); /* destructor */
	void (*exit)(struct io_context *); /* called on task exit */

	struct rcu_head rcu_head;
};

/*