08 May, 2007

1 commit

  • This patch provides a new macro

    KMEM_CACHE(, )

    to simplify slab creation. KMEM_CACHE creates a slab with the name of the
    struct, with the size of the struct and with the alignment of the struct.
    Additional slab flags may be specified if necessary.

    Example

    struct test_slab {
    int a,b,c;
    struct list_head;
    } __cacheline_aligned_in_smp;

    test_slab_cache = KMEM_CACHE(test_slab, SLAB_PANIC)

    will create a new slab named "test_slab" of the size sizeof(struct
    test_slab) and aligned to the alignment of test slab. If it fails then we
    panic.

    Signed-off-by: Christoph Lameter
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Christoph Lameter
     

30 Apr, 2007

17 commits

  • We often lookup the same queue many times in succession, so cache
    the last looked up queue to avoid browsing the rbtree.

    Signed-off-by: Jens Axboe

    Jens Axboe
     
  • cfq hash is no more necessary. We always can get cfqq from io context.
    cfq_get_io_context_noalloc() function is introduced, because we don't
    want to allocate cic on merging and checking may_queue. In order to
    identify sync queue we've used hash key = CFQ_KEY_ASYNC. Since hash is
    eliminated we need to use other criterion: sync flag for queue is added.
    In all places where we dig in rb_tree we're in current context, so no
    additional locking is required.

    Advantages of this patch: no additional memory for hash, no seeking in
    hash, code is cleaner. But it is necessary now to seek cic in per-ioc
    rbtree, but it is faster:
    - most processes work only with few devices
    - most systems have only few block devices
    - it is a rb-tree

    Signed-off-by: Vasily Tarasov

    Changes by me:

    - Merge into CFQ devel branch
    - Get rid of cfq_get_io_context_noalloc()
    - Fix various bugs with dereferencing cic->cfqq[] with offset other
    than 0 or 1.
    - Fix bug in cfqq setup, is_sync condition was reversed.
    - Fix bug where only bio_sync() is used, we need to check for a READ too

    Signed-off-by: Jens Axboe

    Vasily Tarasov
     
  • For tagged devices, allow overlap of requests if the idle window
    isn't enabled on the current active queue.

    Signed-off-by: Jens Axboe

    Jens Axboe
     
  • Signed-off-by: Jens Axboe

    Jens Axboe
     
  • We don't enable it by default, don't let it get enabled during
    runtime.

    Signed-off-by: Jens Axboe

    Jens Axboe
     
  • We can track it fairly accurately locally, let the slice handling
    take care of the rest.

    Signed-off-by: Jens Axboe

    Jens Axboe
     
  • We don't use it anymore in the slice expiry handling.

    Signed-off-by: Jens Axboe

    Jens Axboe
     
  • It's only used for preemption now that the IDLE and RT queues also
    use the rbtree. If we pass an 'add_front' variable to
    cfq_service_tree_add(), we can set ->rb_key to 0 to force insertion
    at the front of the tree.

    Signed-off-by: Jens Axboe

    Jens Axboe
     
  • Use the max_slice-cur_slice as the multipler for the insertion offset.

    Signed-off-by: Jens Axboe

    Jens Axboe
     
  • Signed-off-by: Jens Axboe

    Jens Axboe
     
  • Same treatment as the RT conversion, just put the sorted idle
    branch at the end of the tree.

    Signed-off-by: Jens Axboe

    Jens Axboe
     
  • Currently CFQ does a linked insert into the current list for RT
    queues. We can just factor the class into the rb insertion,
    and then we don't have to treat RT queues in a special way. It's
    faster, too.

    Signed-off-by: Jens Axboe

    Jens Axboe
     
  • For cases where the rbtree is mainly used for sorting and min retrieval,
    a nice speedup of the rbtree code is to maintain a cache of the leftmost
    node in the tree.

    Also spotted in the CFS CPU scheduler code.

    Improved by Alan D. Brunelle by updating the
    leftmost hint in cfq_rb_first() if it isn't set, instead of only
    updating it on insert.

    Signed-off-by: Jens Axboe

    Jens Axboe
     
  • Drawing on some inspiration from the CFS CPU scheduler design, overhaul
    the pending cfq_queue concept list management. Currently CFQ uses a
    doubly linked list per priority level for sorting and service uses.
    Kill those lists and maintain an rbtree of cfq_queue's, sorted by when
    to service them.

    This unfortunately means that the ionice levels aren't as strong
    anymore, will work on improving those later. We only scale the slice
    time now, not the number of times we service. This means that latency
    is better (for all priority levels), but that the distinction between
    the highest and lower levels aren't as big.

    The diffstat speaks for itself.

    cfq-iosched.c | 363 +++++++++++++++++---------------------------------
    1 file changed, 125 insertions(+), 238 deletions(-)

    Signed-off-by: Jens Axboe

    Jens Axboe
     
  • - Move the queue_new flag clear to when the queue is selected
    - Only select the non-first queue in cfq_get_best_queue(), if there's
    a substantial difference between the best and first.
    - Get rid of ->busy_rr
    - Only select a close cooperator, if the current queue is known to take
    a while to "think".

    Signed-off-by: Jens Axboe

    Jens Axboe
     
  • - Implement logic for detecting cooperating processes, so we
    choose the best available queue whenever possible.

    - Improve residual slice time accounting.

    - Remove dead code: we no longer see async requests coming in on
    sync queues. That part was removed a long time ago. That means
    that we can also remove the difference between cfq_cfqq_sync()
    and cfq_cfqq_class_sync(), they are now indentical. And we can
    kill the on_dispatch array, just make it a counter.

    - Allow a process to go into the current list, if it hasn't been
    serviced in this scheduler tick yet.

    Possible future improvements including caching the cfqq lookup
    in cfq_close_cooperator(), so we don't have to look it up twice.
    cfq_get_best_queue() should just use that last decision instead
    of doing it again.

    Signed-off-by: Jens Axboe

    Jens Axboe
     
  • When testing the syslet async io approach, I discovered that CFQ
    sometimes didn't perform as well as expected. cfq_should_preempt()
    needs to better check for cooperating tasks, so fix that by allowing
    preemption of an equal priority queue if the recently queued request
    is as good a candidate for IO as the one we are currently waiting for.

    Signed-off-by: Jens Axboe

    Jens Axboe
     

25 Apr, 2007

1 commit

  • There's a really rare and obscure bug in CFQ, that causes a crash in
    cfq_dispatch_insert() due to rq == NULL. One example of the resulting
    oops is seen here:

    http://lkml.org/lkml/2007/4/15/41

    Neil correctly diagnosed the situation for how this can happen: if two
    concurrent requests with the exact same sector number (due to direct IO
    or aliasing between MD and the raw device access), the alias handling
    will add the request to the sortlist, but next_rq remains NULL.

    Read the more complete analysis at:

    http://lkml.org/lkml/2007/4/25/57

    This looks like it requires md to trigger, even though it should
    potentially be possible to due with O_DIRECT (at least if you edit the
    kernel and doctor some of the unplug calls).

    The fix is to move the ->next_rq update to when we add a request to the
    rbtree. Then we remove the possibility for a request to exist in the
    rbtree code, but not have ->next_rq correctly updated.

    Signed-off-by: Jens Axboe
    Signed-off-by: Linus Torvalds

    Jens Axboe
     

21 Apr, 2007

1 commit

  • We have a 10-15% performance regression for sequential writes on TCQ/NCQ
    enabled drives in 2.6.21-rcX after the CFQ update went in. It has been
    reported by Valerie Clement and the Intel
    testing folks. The regression is because of CFQ's now more aggressive
    queue control, limiting the depth available to the device.

    This patches fixes that regression by allowing a greater depth when only
    one queue is busy. It has been tested to not impact sync-vs-async
    workloads too much - we still do a lot better than 2.6.20.

    Signed-off-by: Jens Axboe
    Signed-off-by: Linus Torvalds

    Jens Axboe
     

12 Feb, 2007

11 commits


03 Jan, 2007

1 commit

  • Two issues:

    - The final return 1 should be a return 0, otherwise comparing cfqq is
    a noop.

    - bio_sync() only checks the sync flag, while rq_is_sync() checks both
    for READ and sync. The latter is what we want. Expand the bio check
    to include reads, and relax the restriction to allow merging of async
    io into sync requests.

    In the future we want to clean up the SYNC logic, right now it means
    both sync request (such as READ and O_DIRECT WRITE) and unplug-on-issue.
    Leave that for later.

    Signed-off-by: Jens Axboe
    Signed-off-by: Linus Torvalds

    Jens Axboe
     

23 Dec, 2006

1 commit

  • The logic in cfq_allow_merge() wasn't clear enough - basically allow
    merging for the same queues only. Do a fast check for 'rq and bio both
    sync/async' before doing the cfqq hash lookup.

    This is verified to work with the fixed elv_try_merge() from commit
    bb4067e34159648d394943d5e2a011f838bff22f.

    Signed-off-by: Jens Axboe
    Signed-off-by: Linus Torvalds

    Jens Axboe
     

20 Dec, 2006

1 commit

  • Currently we allow any merge, even if the io originates from different
    processes. This can cause really bad starvation and unfairness, if those
    ios happen to be synchronous (reads or direct writes).

    So add a allow_merge hook to the io scheduler ops, so an io scheduler can
    help decide whether a bio/process combination may be merged with an
    existing request.

    Signed-off-by: Jens Axboe

    Jens Axboe
     

13 Dec, 2006

1 commit


08 Dec, 2006

1 commit

  • Replace all uses of kmem_cache_t with struct kmem_cache.

    The patch was generated using the following script:

    #!/bin/sh
    #
    # Replace one string by another in all the kernel sources.
    #

    set -e

    for file in `find * -name "*.c" -o -name "*.h"|xargs grep -l $1`; do
    quilt add $file
    sed -e "1,\$s/$1/$2/g" $file >/tmp/$$
    mv /tmp/$$ $file
    quilt refresh
    done

    The script was run like this

    sh replace kmem_cache_t "struct kmem_cache"

    Signed-off-by: Christoph Lameter
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Christoph Lameter
     

05 Dec, 2006

1 commit


01 Dec, 2006

1 commit


22 Nov, 2006

1 commit

  • Pass the work_struct pointer to the work function rather than context data.
    The work function can use container_of() to work out the data.

    For the cases where the container of the work_struct may go away the moment the
    pending bit is cleared, it is made possible to defer the release of the
    structure by deferring the clearing of the pending bit.

    To make this work, an extra flag is introduced into the management side of the
    work_struct. This governs auto-release of the structure upon execution.

    Ordinarily, the work queue executor would release the work_struct for further
    scheduling or deallocation by clearing the pending bit prior to jumping to the
    work function. This means that, unless the driver makes some guarantee itself
    that the work_struct won't go away, the work function may not access anything
    else in the work_struct or its container lest they be deallocated.. This is a
    problem if the auxiliary data is taken away (as done by the last patch).

    However, if the pending bit is *not* cleared before jumping to the work
    function, then the work function *may* access the work_struct and its container
    with no problems. But then the work function must itself release the
    work_struct by calling work_release().

    In most cases, automatic release is fine, so this is the default. Special
    initiators exist for the non-auto-release case (ending in _NAR).

    Signed-Off-By: David Howells

    David Howells
     

01 Nov, 2006

1 commit

  • In very rare circumstances would we be pruning a merged request and at
    the same time delete the implicated cfqq from the rr_list, and not readd
    it when the merged request got added. This could cause io stalls until
    that process issued io again.

    Fix it up by putting the rr_list add handling into cfq_add_rq_rb(),
    identical to how pruning is handled in cfq_del_rq_rb(). This fixes a
    hang reproducible with fsx-linux.

    Signed-off-by: Jens Axboe
    Signed-off-by: Linus Torvalds

    Jens Axboe