14 Dec, 2011

3 commits

  • cic is association between io_context and request_queue. A cic is
    linked from both ioc and q and should be destroyed when either one
    goes away. As ioc and q both have their own locks, locking becomes a
    bit complex - both orders work for removal from one but not from the
    other.

    Currently, cfq tries to circumvent this locking order issue with RCU.
    ioc->lock nests inside queue_lock but the radix tree and cic's are
    also protected by RCU allowing either side to walk their lists without
    grabbing lock.

    This rather unconventional use of RCU quickly devolves into extremely
    fragile convolution. e.g. The following is from cfqd going away too
    soon after ioc and q exits raced.

    general protection fault: 0000 [#1] PREEMPT SMP
    CPU 2
    Modules linked in:
    [ 88.503444]
    Pid: 599, comm: hexdump Not tainted 3.1.0-rc10-work+ #158 Bochs Bochs
    RIP: 0010:[] [] cfq_exit_single_io_context+0x58/0xf0
    ...
    Call Trace:
    [] call_for_each_cic+0x5a/0x90
    [] cfq_exit_io_context+0x15/0x20
    [] exit_io_context+0x100/0x140
    [] do_exit+0x579/0x850
    [] do_group_exit+0x5b/0xd0
    [] sys_exit_group+0x17/0x20
    [] system_call_fastpath+0x16/0x1b

    The only real hot path here is cic lookup during request
    initialization and avoiding extra locking requires very confined use
    of RCU. This patch makes cic removal from both ioc and request_queue
    perform double-locking and unlink immediately.

    * From q side, the change is almost trivial as ioc->lock nests inside
    queue_lock. It just needs to grab each ioc->lock as it walks
    cic_list and unlink it.

    * From ioc side, it's a bit more difficult because of inversed lock
    order. ioc needs its lock to walk its cic_list but can't grab the
    matching queue_lock and needs to perform unlock-relock dancing.

    Unlinking is now wholly done from put_io_context() and fast path is
    optimized by using the queue_lock the caller already holds, which is
    by far the most common case. If the ioc accessed multiple devices,
    it tries with trylock. In unlikely cases of fast path failure, it
    falls back to full double-locking dance from workqueue.

    Double-locking isn't the prettiest thing in the world but it's *far*
    simpler and more understandable than RCU trick without adding any
    meaningful overhead.

    This still leaves a lot of now unnecessary RCU logics. Future patches
    will trim them.

    -v2: Vivek pointed out that cic->q was being dereferenced after
    cic->release() was called. Updated to use local variable @this_q
    instead.

    Signed-off-by: Tejun Heo
    Cc: Vivek Goyal
    Signed-off-by: Jens Axboe

    Tejun Heo
     
  • ioprio/cgroup change was handled by marking the changed state in ioc
    and, on the following access to the ioc, performing RCU-protected
    iteration through all cic's grabbing the matching queue_lock.

    This patch moves the changed state to each cic. When ioprio or cgroup
    changes, the respective bit is set on all cic's of the ioc and when
    each of those cic (not ioc) is accessed, change is applied for that
    specific ioc-queue pair.

    This also fixes the following two race conditions between setting and
    clearing of changed states.

    * Missing barrier between assign/load of ioprio and ioprio_changed
    allowed applying old ioprio.

    * Change requests could happen between application of change and
    clearing of changed variables.

    Signed-off-by: Tejun Heo
    Signed-off-by: Jens Axboe

    Tejun Heo
     
  • Ignoring copy_io() during fork, io_context can be allocated from two
    places - current_io_context() and set_task_ioprio(). The former is
    always called from local task while the latter can be called from
    different task. The synchornization between them are peculiar and
    dubious.

    * current_io_context() doesn't grab task_lock() and assumes that if it
    saw %NULL ->io_context, it would stay that way until allocation and
    assignment is complete. It has smp_wmb() between alloc/init and
    assignment.

    * set_task_ioprio() grabs task_lock() for assignment and does
    smp_read_barrier_depends() between "ioc = task->io_context" and "if
    (ioc)". Unfortunately, this doesn't achieve anything - the latter
    is not a dependent load of the former. ie, if ioc itself were being
    dereferenced "ioc->xxx", it would mean something (not sure what tho)
    but as the code currently stands, the dependent read barrier is
    noop.

    As only one of the the two test-assignment sequences is task_lock()
    protected, the task_lock() can't do much about race between the two.
    Nothing prevents current_io_context() and set_task_ioprio() allocating
    its own ioc for the same task and overwriting the other's.

    Also, set_task_ioprio() can race with exiting task and create a new
    ioc after exit_io_context() is finished.

    ioc get/put doesn't have any reason to be complex. The only hot path
    is accessing the existing ioc of %current, which is simple to achieve
    given that ->io_context is never destroyed as long as the task is
    alive. All other paths can happily go through task_lock() like all
    other task sub structures without impacting anything.

    This patch updates ioc get/put so that it becomes more conventional.

    * alloc_io_context() is replaced with get_task_io_context(). This is
    the only interface which can acquire access to ioc of another task.
    On return, the caller has an explicit reference to the object which
    should be put using put_io_context() afterwards.

    * The functionality of current_io_context() remains the same but when
    creating a new ioc, it shares the code path with
    get_task_io_context() and always goes through task_lock().

    * get_io_context() now means incrementing ref on an ioc which the
    caller already has access to (be that an explicit refcnt or implicit
    %current one).

    * PF_EXITING inhibits creation of new io_context and once
    exit_io_context() is finished, it's guaranteed that both ioc
    acquisition functions return %NULL.

    * All users are updated. Most are trivial but
    smp_read_barrier_depends() removal from cfq_get_io_context() needs a
    bit of explanation. I suppose the original intention was to ensure
    ioc->ioprio is visible when set_task_ioprio() allocates new
    io_context and installs it; however, this wouldn't have worked
    because set_task_ioprio() doesn't have wmb between init and install.
    There are other problems with this which will be fixed in another
    patch.

    * While at it, use NUMA_NO_NODE instead of -1 for wildcard node
    specification.

    -v2: Vivek spotted contamination from debug patch. Removed.

    Signed-off-by: Tejun Heo
    Cc: Vivek Goyal
    Signed-off-by: Jens Axboe

    Tejun Heo
     

01 Nov, 2011

1 commit


15 Nov, 2010

1 commit

  • Using:
    - CONFIG_LOCKUP_DETECTOR=y
    - CONFIG_PREEMPT=y
    - CONFIG_LOCKDEP=y
    - CONFIG_PROVE_LOCKING=y
    - CONFIG_PROVE_RCU=y
    found a missing rcu lock during boot on a 512 MiB x86_64 ubuntu vm:
    ===================================================
    [ INFO: suspicious rcu_dereference_check() usage. ]
    ---------------------------------------------------
    kernel/pid.c:419 invoked rcu_dereference_check() without protection!

    other info that might help us debug this:

    rcu_scheduler_active = 1, debug_locks = 0
    1 lock held by ureadahead/1355:
    #0: (tasklist_lock){.+.+..}, at: [] sys_ioprio_set+0x7f/0x29e

    stack backtrace:
    Pid: 1355, comm: ureadahead Not tainted 2.6.37-dbg-DEV #1
    Call Trace:
    [] lockdep_rcu_dereference+0xaa/0xb3
    [] find_task_by_pid_ns+0x44/0x5d
    [] find_task_by_vpid+0x22/0x24
    [] sys_ioprio_set+0xb4/0x29e
    [] ? trace_hardirqs_off_thunk+0x3a/0x3c
    [] sysenter_dispatch+0x7/0x2c
    [] ? trace_hardirqs_on_thunk+0x3a/0x3f

    The fix is to:
    a) grab rcu lock in sys_ioprio_{set,get}() and
    b) avoid grabbing tasklist_lock.
    Discussion in: http://marc.info/?l=linux-kernel&m=128951324702889

    Signed-off-by: Greg Thelen
    Acked-by: Paul E. McKenney
    Reviewed-by: Oleg Nesterov

    Modified by Jens to remove the now redundant inner rcu lock and
    unlock since they are now protected by the outer lock.

    Signed-off-by: Jens Axboe

    Greg Thelen
     

10 Nov, 2010

2 commits

  • Commit 4221a9918e38b7494cee341dda7b7b4bb8c04bde "Add RCU check for
    find_task_by_vpid()" introduced rcu_lockdep_assert to find_task_by_pid_ns=

    Assertion failed in sys_ioprio_get. The patch is fixing assertion
    failure in ioprio_set as well.

    kernel/pid.c:419 invoked rcu_dereference_check() without protection!

    stack backtrace:
    Pid: 4254, comm: iotop Not tainted
    Call Trace:
    [] lockdep_rcu_dereference+0xaa/0xb2
    [] find_task_by_pid_ns+0x4f/0x68
    [] find_task_by_vpid+0x1d/0x1f
    [] sys_ioprio_get+0x50/0x2da
    [] system_call_fastpath+0x16/0x1b

    V2: rcu critical section expanded according to comment by Paul E. McKenney

    Signed-off-by: Sergey Senozhatsky
    Acked-by: Paul E. McKenney
    Signed-off-by: Jens Axboe

    Sergey Senozhatsky
     
  • With 2.6.37-rc1, I observe sys_ioprio_set not taking the RCU lock [1]
    across access to the task credentials.

    Inspecting the code in fs/ioprio.c, the tasklist_lock is held for read
    across the __task_cred call, which is presumably sufficient to prevent
    the task credentials becoming stale.

    ===================================================

    [ INFO: suspicious rcu_dereference_check() usage. ]

    ---------------------------------------------------

    kernel/pid.c:419 invoked rcu_dereference_check() without protection!

    other info that might help us debug this:

    rcu_scheduler_active = 1, debug_locks = 1

    1 lock held by start-stop-daem/2246:

    #0: (tasklist_lock){.?.?..}, at: []
    sys_ioprio_set+0x8a/0x400

    stack backtrace:

    Pid: 2246, comm: start-stop-daem Not tainted 2.6.37-rc1-330cd+ #2

    Call Trace:

    [] lockdep_rcu_dereference+0xa4/0xc0

    [] find_task_by_pid_ns+0x81/0x90

    [] find_task_by_vpid+0x1d/0x20

    [] sys_ioprio_set+0x3f0/0x400

    [] ? trace_hardirqs_on_thunk+0x3a/0x3f

    [] system_call_fastpath+0x16/0x1b

    Take the RCU lock for read across acquiring the pointer to the task
    credentials and dereferencing it.

    Signed-off-by: Daniel J Blueman

    Fixed up by Jens to fix missing rcu_read_unlock() on mismatches.

    Signed-off-by: Jens Axboe

    Daniel J Blueman
     

30 Mar, 2010

1 commit

  • …it slab.h inclusion from percpu.h

    percpu.h is included by sched.h and module.h and thus ends up being
    included when building most .c files. percpu.h includes slab.h which
    in turn includes gfp.h making everything defined by the two files
    universally available and complicating inclusion dependencies.

    percpu.h -> slab.h dependency is about to be removed. Prepare for
    this change by updating users of gfp and slab facilities include those
    headers directly instead of assuming availability. As this conversion
    needs to touch large number of source files, the following script is
    used as the basis of conversion.

    http://userweb.kernel.org/~tj/misc/slabh-sweep.py

    The script does the followings.

    * Scan files for gfp and slab usages and update includes such that
    only the necessary includes are there. ie. if only gfp is used,
    gfp.h, if slab is used, slab.h.

    * When the script inserts a new include, it looks at the include
    blocks and try to put the new include such that its order conforms
    to its surrounding. It's put in the include block which contains
    core kernel includes, in the same order that the rest are ordered -
    alphabetical, Christmas tree, rev-Xmas-tree or at the end if there
    doesn't seem to be any matching order.

    * If the script can't find a place to put a new include (mostly
    because the file doesn't have fitting include block), it prints out
    an error message indicating which .h file needs to be added to the
    file.

    The conversion was done in the following steps.

    1. The initial automatic conversion of all .c files updated slightly
    over 4000 files, deleting around 700 includes and adding ~480 gfp.h
    and ~3000 slab.h inclusions. The script emitted errors for ~400
    files.

    2. Each error was manually checked. Some didn't need the inclusion,
    some needed manual addition while adding it to implementation .h or
    embedding .c file was more appropriate for others. This step added
    inclusions to around 150 files.

    3. The script was run again and the output was compared to the edits
    from #2 to make sure no file was left behind.

    4. Several build tests were done and a couple of problems were fixed.
    e.g. lib/decompress_*.c used malloc/free() wrappers around slab
    APIs requiring slab.h to be added manually.

    5. The script was run on all .h files but without automatically
    editing them as sprinkling gfp.h and slab.h inclusions around .h
    files could easily lead to inclusion dependency hell. Most gfp.h
    inclusion directives were ignored as stuff from gfp.h was usually
    wildly available and often used in preprocessor macros. Each
    slab.h inclusion directive was examined and added manually as
    necessary.

    6. percpu.h was updated not to include slab.h.

    7. Build test were done on the following configurations and failures
    were fixed. CONFIG_GCOV_KERNEL was turned off for all tests (as my
    distributed build env didn't work with gcov compiles) and a few
    more options had to be turned off depending on archs to make things
    build (like ipr on powerpc/64 which failed due to missing writeq).

    * x86 and x86_64 UP and SMP allmodconfig and a custom test config.
    * powerpc and powerpc64 SMP allmodconfig
    * sparc and sparc64 SMP allmodconfig
    * ia64 SMP allmodconfig
    * s390 SMP allmodconfig
    * alpha SMP allmodconfig
    * um on x86_64 SMP allmodconfig

    8. percpu.h modifications were reverted so that it could be applied as
    a separate patch and serve as bisection point.

    Given the fact that I had only a couple of failures from tests on step
    6, I'm fairly confident about the coverage of this conversion patch.
    If there is a breakage, it's likely to be something in one of the arch
    headers which should be easily discoverable easily on most builds of
    the specific arch.

    Signed-off-by: Tejun Heo <tj@kernel.org>
    Guess-its-ok-by: Christoph Lameter <cl@linux-foundation.org>
    Cc: Ingo Molnar <mingo@redhat.com>
    Cc: Lee Schermerhorn <Lee.Schermerhorn@hp.com>

    Tejun Heo
     

14 Jan, 2009

1 commit


06 Jan, 2009

1 commit


14 Nov, 2008

4 commits

  • Use RCU to access another task's creds and to release a task's own creds.
    This means that it will be possible for the credentials of a task to be
    replaced without another task (a) requiring a full lock to read them, and (b)
    seeing deallocated memory.

    Signed-off-by: David Howells
    Acked-by: James Morris
    Acked-by: Serge Hallyn
    Signed-off-by: James Morris

    David Howells
     
  • Wrap current->cred and a few other accessors to hide their actual
    implementation.

    Signed-off-by: David Howells
    Acked-by: James Morris
    Acked-by: Serge Hallyn
    Signed-off-by: James Morris

    David Howells
     
  • Separate the task security context from task_struct. At this point, the
    security data is temporarily embedded in the task_struct with two pointers
    pointing to it.

    Note that the Alpha arch is altered as it refers to (E)UID and (E)GID in
    entry.S via asm-offsets.

    With comment fixes Signed-off-by: Marc Dionne

    Signed-off-by: David Howells
    Acked-by: James Morris
    Acked-by: Serge Hallyn
    Signed-off-by: James Morris

    David Howells
     
  • Wrap access to task credentials so that they can be separated more easily from
    the task_struct during the introduction of COW creds.

    Change most current->(|e|s|fs)[ug]id to current_(|e|s|fs)[ug]id().

    Change some task->e?[ug]id to task_e?[ug]id(). In some places it makes more
    sense to use RCU directly rather than a convenient wrapper; these will be
    addressed by later patches.

    Signed-off-by: David Howells
    Reviewed-by: James Morris
    Acked-by: Serge Hallyn
    Cc: Al Viro
    Signed-off-by: James Morris

    David Howells
     

21 Aug, 2008

1 commit

  • When user calls sys_setpriority(PRIO_PGRP ...) on a NPTL style multi-LWP
    process, only the task leader of the process is affected, all other
    sibling LWP threads didn't receive the setting. The problem was that the
    iterator used in sys_setpriority() only iteartes over one task for each
    process, ignoring all other sibling thread.

    Introduce a new macro do_each_pid_thread / while_each_pid_thread to walk
    each thread of a process. Convert 4 call sites in {set/get}priority and
    ioprio_{set/get}.

    Signed-off-by: Ken Chen
    Cc: Oleg Nesterov
    Cc: Roland McGrath
    Cc: Ingo Molnar
    Cc: Thomas Gleixner
    Cc: Jens Axboe
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Ken Chen
     

28 Jan, 2008

3 commits

  • Currently you must be root to set idle io prio class on a process. This
    is due to the fact that the idle class is implemented as a true idle
    class, meaning that it will not make progress if someone else is
    requesting disk access. Unfortunately this means that it opens DOS
    opportunities by locking down file system resources, hence it is root
    only at the moment.

    This patch relaxes the idle class a little, by removing the truly idle
    part (which entals a grace period with associated timer). The
    modifications make the idle class as close to zero impact as can be done
    while still guarenteeing progress. This means we can relax the root only
    criteria as well.

    Signed-off-by: Jens Axboe

    Jens Axboe
     
  • Detach task state from ioc, instead keep track of how many processes
    are accessing the ioc.

    Signed-off-by: Jens Axboe

    Jens Axboe
     
  • This is where it belongs and then it doesn't take up space for a
    process that doesn't do IO.

    Signed-off-by: Jens Axboe

    Jens Axboe
     

07 Nov, 2007

1 commit

  • Normally io priorities follow the CPU nice, unless a specific scheduling
    class has been set. Once that is set, there's no way to reset the
    behaviour to 'none' so that it follows CPU nice again.

    Currently passing in 0 as the ioprio class/value will return -1/EINVAL,
    change that to allow resetting of a set scheduling class.

    Signed-off-by: Jens Axboe

    Jens Axboe
     

20 Oct, 2007

2 commits

  • The find_task_by_something is a set of macros are used to find task by pid
    depending on what kind of pid is proposed - global or virtual one. All of
    them are wrappers above the most generic one - find_task_by_pid_type_ns() -
    and just substitute some args for it.

    It turned out, that dereferencing the current->nsproxy->pid_ns construction
    and pushing one more argument on the stack inline cause kernel text size to
    grow.

    This patch moves all this stuff out-of-line into kernel/pid.c. Together
    with the next patch it saves a bit less than 400 bytes from the .text
    section.

    Signed-off-by: Pavel Emelyanov
    Cc: Sukadev Bhattiprolu
    Cc: Oleg Nesterov
    Cc: Paul Menage
    Cc: "Eric W. Biederman"
    Acked-by: Ingo Molnar
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Pavel Emelyanov
     
  • This is the largest patch in the set. Make all (I hope) the places where
    the pid is shown to or get from user operate on the virtual pids.

    The idea is:
    - all in-kernel data structures must store either struct pid itself
    or the pid's global nr, obtained with pid_nr() call;
    - when seeking the task from kernel code with the stored id one
    should use find_task_by_pid() call that works with global pids;
    - when showing pid's numerical value to the user the virtual one
    should be used, but however when one shows task's pid outside this
    task's namespace the global one is to be used;
    - when getting the pid from userspace one need to consider this as
    the virtual one and use appropriate task/pid-searching functions.

    [akpm@linux-foundation.org: build fix]
    [akpm@linux-foundation.org: nuther build fix]
    [akpm@linux-foundation.org: yet nuther build fix]
    [akpm@linux-foundation.org: remove unneeded casts]
    Signed-off-by: Pavel Emelyanov
    Signed-off-by: Alexey Dobriyan
    Cc: Sukadev Bhattiprolu
    Cc: Oleg Nesterov
    Cc: Paul Menage
    Cc: "Eric W. Biederman"
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Pavel Emelyanov
     

13 Feb, 2007

1 commit


12 Oct, 2006

1 commit

  • Currently ioprio_best function first checks wethere aioprio or bioprio equals
    IOPRIO_CLASS_NONE (ioprio_valid() macros does that) and if it is so it returns
    bioprio/aioprio appropriately. Thus the next four lines, that set aclass/bclass
    to IOPRIO_CLASS_BE, if aclass/bclass == IOPRIO_CLASS_NONE, are never executed.

    The second problem: if aioprio from class IOPRIO_CLASS_NONE and bioprio from
    class IOPRIO_CLASS_IDLE are passed to ioprio_best function, it will return
    IOPRIO_CLASS_IDLE. It means that during __make_request we can merge two
    requests and set the priority of merged request to IDLE, while one of
    the initial requests originates from a process with NONE (default) priority.
    So we can get a situation when a process with default ioprio will experience
    IO starvation, while there is no process from real-time class in the system.

    Just removing ioprio_valid check should correct situation.

    Signed-off-by: Vasily Tarasov
    Signed-off-by: Jens Axboe

    Vasily Tarasov
     

01 Oct, 2006

3 commits

  • As people often look for the copyright in files to see who to mail,
    update the link to a neutral one.

    Signed-off-by: Jens Axboe

    Jens Axboe
     
  • Signed-off-by: Oleg Nesterov
    Signed-off-by: Jens Axboe

    Oleg Nesterov
     
  • cfq_exit_lock is protecting two things now:

    - The per-ioc rbtree of cfq_io_contexts

    - The per-cfqd linked list of cfq_io_contexts

    The per-cfqd linked list can be protected by the queue lock, as it is (by
    definition) per cfqd as the queue lock is.

    The per-ioc rbtree is mainly used and updated by the process itself only.
    The only outside use is the io priority changing. If we move the
    priority changing to not browsing the rbtree, we can remove any locking
    from the rbtree updates and lookup completely. Let the sys_ioprio syscall
    just mark processes as having the iopriority changed and lazily update
    the private cfq io contexts the next time io is queued, and we can
    remove this locking as well.

    Signed-off-by: Jens Axboe

    Jens Axboe
     

21 Aug, 2006

3 commits


01 Jul, 2006

1 commit

  • Add a new security hook definition for the sys_ioprio_get operation. At
    present, the SELinux hook function implementation for this hook is
    identical to the getscheduler implementation but a separate hook is
    introduced to allow this check to be specialized in the future if
    necessary.

    This patch also creates a helper function get_task_ioprio which handles the
    access check in addition to retrieving the ioprio value for the task.

    Signed-off-by: David Quigley
    Acked-by: Stephen Smalley
    Signed-off-by: James Morris
    Cc: Jens Axboe
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    David Quigley
     

23 Jun, 2006

1 commit

  • Implement an LSM hook for setting a task's IO priority, similar to the hook
    for setting a tasks's nice value.

    A previous version of this LSM hook was included in an older version of
    multiadm by Jan Engelhardt, although I don't recall it being submitted
    upstream.

    Also included is the corresponding SELinux hook, which re-uses the setsched
    permission in the proccess class.

    Signed-off-by: James Morris
    Acked-by: Stephen Smalley
    Cc: Jan Engelhardt
    Cc: Chris Wright
    Cc: Jens Axboe
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    James Morris
     

12 Jan, 2006

1 commit


08 Nov, 2005

1 commit


21 Aug, 2005

1 commit


08 Jul, 2005

1 commit

  • - Make ioprio syscalls return long, like set/getpriority syscalls.
    - Move function prototypes into syscalls.h so we can pick them up in the
    32/64bit compat code.

    Signed-off-by: Anton Blanchard
    Acked-by: Jens Axboe
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Anton Blanchard
     

28 Jun, 2005

1 commit

  • This updates the CFQ io scheduler to the new time sliced design (cfq
    v3). It provides full process fairness, while giving excellent
    aggregate system throughput even for many competing processes. It
    supports io priorities, either inherited from the cpu nice value or set
    directly with the ioprio_get/set syscalls. The latter closely mimic
    set/getpriority.

    This import is based on my latest from -mm.

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

    Jens Axboe