15 Oct, 2019

1 commit

  • Fix (Sphinx) kernel-doc warning in :

    include/linux/xarray.h:232: WARNING: Unexpected indentation.

    Link: http://lkml.kernel.org/r/89ba2134-ce23-7c10-5ee1-ef83b35aa984@infradead.org
    Fixes: a3e4d3f97ec8 ("XArray: Redesign xa_alloc API")
    Signed-off-by: Randy Dunlap
    Cc: Matthew Wilcox
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Randy Dunlap
     

01 Jun, 2019

1 commit

  • Since a28334862993 ("page cache: Finish XArray conversion"), on most
    major Linux distributions, the page cache doesn't correctly transition
    when the hot data set is changing, and leaves the new pages thrashing
    indefinitely instead of kicking out the cold ones.

    On a freshly booted, freshly ssh'd into virtual machine with 1G RAM
    running stock Arch Linux:

    [root@ham ~]# ./reclaimtest.sh
    + dd of=workingset-a bs=1M count=0 seek=600
    + cat workingset-a
    + cat workingset-a
    + cat workingset-a
    + cat workingset-a
    + cat workingset-a
    + cat workingset-a
    + cat workingset-a
    + cat workingset-a
    + ./mincore workingset-a
    153600/153600 workingset-a
    + dd of=workingset-b bs=1M count=0 seek=600
    + cat workingset-b
    + cat workingset-b
    + cat workingset-b
    + cat workingset-b
    + ./mincore workingset-a workingset-b
    104029/153600 workingset-a
    120086/153600 workingset-b
    + cat workingset-b
    + cat workingset-b
    + cat workingset-b
    + cat workingset-b
    + ./mincore workingset-a workingset-b
    104029/153600 workingset-a
    120268/153600 workingset-b

    workingset-b is a 600M file on a 1G host that is otherwise entirely
    idle. No matter how often it's being accessed, it won't get cached.

    While investigating, I noticed that the non-resident information gets
    aggressively reclaimed - /proc/vmstat::workingset_nodereclaim. This is
    a problem because a workingset transition like this relies on the
    non-resident information tracked in the page cache tree of evicted
    file ranges: when the cache faults are refaults of recently evicted
    cache, we challenge the existing active set, and that allows a new
    workingset to establish itself.

    Tracing the shrinker that maintains this memory revealed that all page
    cache tree nodes were allocated to the root cgroup. This is a problem,
    because 1) the shrinker sizes the amount of non-resident information
    it keeps to the size of the cgroup's other memory and 2) on most major
    Linux distributions, only kernel threads live in the root cgroup and
    everything else gets put into services or session groups:

    [root@ham ~]# cat /proc/self/cgroup
    0::/user.slice/user-0.slice/session-c1.scope

    As a result, we basically maintain no non-resident information for the
    workloads running on the system, thus breaking the caching algorithm.

    Looking through the code, I found the culprit in the above-mentioned
    patch: when switching from the radix tree to xarray, it dropped the
    __GFP_ACCOUNT flag from the tree node allocations - the flag that
    makes sure the allocated memory gets charged to and tracked by the
    cgroup of the calling process - in this case, the one doing the fault.

    To fix this, allow xarray users to specify per-tree flag that makes
    xarray allocate nodes using __GFP_ACCOUNT. Then restore the page cache
    tree annotation to request such cgroup tracking for the cache nodes.

    With this patch applied, the page cache correctly converges on new
    workingsets again after just a few iterations:

    [root@ham ~]# ./reclaimtest.sh
    + dd of=workingset-a bs=1M count=0 seek=600
    + cat workingset-a
    + cat workingset-a
    + cat workingset-a
    + cat workingset-a
    + cat workingset-a
    + cat workingset-a
    + cat workingset-a
    + cat workingset-a
    + ./mincore workingset-a
    153600/153600 workingset-a
    + dd of=workingset-b bs=1M count=0 seek=600
    + cat workingset-b
    + ./mincore workingset-a workingset-b
    124607/153600 workingset-a
    87876/153600 workingset-b
    + cat workingset-b
    + ./mincore workingset-a workingset-b
    81313/153600 workingset-a
    133321/153600 workingset-b
    + cat workingset-b
    + ./mincore workingset-a workingset-b
    63036/153600 workingset-a
    153600/153600 workingset-b

    Cc: stable@vger.kernel.org # 4.20+
    Signed-off-by: Johannes Weiner
    Reviewed-by: Shakeel Butt
    Signed-off-by: Matthew Wilcox (Oracle)

    Johannes Weiner
     

21 Feb, 2019

2 commits

  • Jason feels this is clearer, and it saves a function and an exported
    symbol.

    Suggested-by: Jason Gunthorpe
    Signed-off-by: Matthew Wilcox

    Matthew Wilcox
     
  • xa_cmpxchg() was a little too magic in turning ZERO entries into NULL,
    and would leave the entry set to the ZERO entry instead of releasing
    it for future use. After careful review of existing users of
    xa_cmpxchg(), change the semantics so that it does not translate either
    incoming argument from NULL into ZERO entries.

    Add several tests to the test-suite to make sure this problem doesn't
    come back.

    Reported-by: Jason Gunthorpe
    Signed-off-by: Matthew Wilcox

    Matthew Wilcox
     

09 Feb, 2019

1 commit


07 Feb, 2019

4 commits

  • This differs slightly from the IDR equivalent in five ways.

    1. It can allocate up to UINT_MAX instead of being limited to INT_MAX,
    like xa_alloc(). Also like xa_alloc(), it will write to the 'id'
    pointer before placing the entry in the XArray.
    2. The 'next' cursor is allocated separately from the XArray instead
    of being part of the IDR. This saves memory for all the users which
    do not use the cyclic allocation API and suits some users better.
    3. It returns -EBUSY instead of -ENOSPC.
    4. It will attempt to wrap back to the minimum value on memory allocation
    failure as well as on an -EBUSY error, assuming that a user would
    rather allocate a small ID than suffer an ID allocation failure.
    5. It reports whether it has wrapped, which is important to some users.

    Signed-off-by: Matthew Wilcox

    Matthew Wilcox
     
  • It was too easy to forget to initialise the start index. Add an
    xa_limit data structure which can be used to pass min & max, and
    define a couple of special values for common cases. Also add some
    more tests cribbed from the IDR test suite. Change the return value
    from -ENOSPC to -EBUSY to match xa_insert().

    Signed-off-by: Matthew Wilcox

    Matthew Wilcox
     
  • A lot of places want to allocate IDs starting at 1 instead of 0.
    While the xa_alloc() API supports this, it's not very efficient if lots
    of IDs are allocated, due to having to walk down to the bottom of the
    tree to see if ID 1 is available, then all the way over to the next
    non-allocated ID. This method marks ID 0 as being occupied which wastes
    one slot in the XArray, but preserves xa_empty() as working.

    Signed-off-by: Matthew Wilcox

    Matthew Wilcox
     
  • Userspace translates EEXIST to "File exists" which isn't a very good
    error message for the problem. "Device or resource busy" is a better
    indication of what went wrong.

    Signed-off-by: Matthew Wilcox

    Matthew Wilcox
     

05 Feb, 2019

1 commit


17 Jan, 2019

1 commit

  • There is a math problem here which leads to a lot of static checker
    warnings for me:

    net/sunrpc/clnt.c:451 rpc_new_client() error: (-4096) too low for ERR_PTR

    Error values are from -1 to -4095 or from 0xffffffff to 0xfffff001 in
    hexadecimal. (I am assuming a 32 bit system for simplicity). We are
    using the lowest two bits to hold some internal XArray data so the
    error is shifted two spaces to the left. 0xfffff001 << 2 is 0xffffc004.
    And finally we want to check that BIT(1) is set so we add 2 which gives
    us 0xffffc006.

    In other words, we should be checking that "entry >= 0xffffc006", but
    the check is actually testing if "entry >= 0xffffc002".

    Fixes: 76b4e5299565 ("XArray: Permit storing 2-byte-aligned pointers")
    Signed-off-by: Dan Carpenter
    [Use xa_mk_internal() instead of changing the bracketing]
    Signed-off-by: Matthew Wilcox

    Dan Carpenter
     

15 Jan, 2019

1 commit


07 Jan, 2019

4 commits

  • xa_insert() should treat reserved entries as occupied, not as available.
    Also, it should treat requests to insert a NULL pointer as a request
    to reserve the slot. Add xa_insert_bh() and xa_insert_irq() for
    completeness.

    Signed-off-by: Matthew Wilcox

    Matthew Wilcox
     
  • On m68k, statically allocated pointers may only be two-byte aligned.
    This clashes with the XArray's method for tagging internal pointers.
    Permit storing these pointers in single slots (ie not in multislots).

    Signed-off-by: Matthew Wilcox

    Matthew Wilcox
     
  • There were three problems with this API:
    1. It took too many arguments; almost all users wanted to iterate over
    every element in the array rather than a subset.
    2. It required that 'index' be initialised before use, and there's no
    realistic way to make GCC catch that.
    3. 'index' and 'entry' were the opposite way round from every other
    member of the XArray APIs.

    So split it into three different APIs:

    xa_for_each(xa, index, entry)
    xa_for_each_start(xa, index, entry, start)
    xa_for_each_marked(xa, index, entry, filter)

    Signed-off-by: Matthew Wilcox

    Matthew Wilcox
     
  • A regular xa_init_flags() put all dynamically-initialised XArrays into
    the same locking class. That leads to lockdep believing that taking
    one XArray lock while holding another is a deadlock. It's possible to
    work around some of these situations with separate locking classes for
    irq/bh/regular XArrays, and SINGLE_DEPTH_NESTING, but that's ugly, and
    it doesn't work for all situations (where we have completely unrelated
    XArrays).

    Signed-off-by: Matthew Wilcox

    Matthew Wilcox
     

06 Dec, 2018

1 commit


06 Nov, 2018

5 commits


21 Oct, 2018

15 commits

  • This version of xa_store_range() really only supports load and store.
    Our only user only needs basic load and store functionality, so there's
    no need to do the extra work to support marking and overlapping stores
    correctly yet.

    Signed-off-by: Matthew Wilcox

    Matthew Wilcox
     
  • Add the optional ability to track which entries in an XArray are free
    and provide xa_alloc() to replace most of the functionality of the IDR.

    Signed-off-by: Matthew Wilcox

    Matthew Wilcox
     
  • This function reserves a slot in the XArray for users which need
    to acquire multiple locks before storing their entry in the tree and
    so cannot use a plain xa_store().

    Signed-off-by: Matthew Wilcox

    Matthew Wilcox
     
  • This hopefully temporary function is useful for users who have not yet
    been converted to multi-index entries.

    Signed-off-by: Matthew Wilcox

    Matthew Wilcox
     
  • This iterator iterates over each entry that is stored in the index or
    indices specified by the xa_state. This is intended for use for a
    conditional store of a multiindex entry, or to allow entries which are
    about to be removed from the xarray to be disposed of properly.

    Signed-off-by: Matthew Wilcox

    Matthew Wilcox
     
  • The xas_next and xas_prev functions move the xas index by one position,
    and adjust the rest of the iterator state to match it. This is more
    efficient than calling xas_set() as it keeps the iterator at the leaves
    of the tree instead of walking the iterator from the root each time.

    Signed-off-by: Matthew Wilcox

    Matthew Wilcox
     
  • This function frees all the internal memory allocated to the xarray
    and reinitialises it to be empty.

    Signed-off-by: Matthew Wilcox

    Matthew Wilcox
     
  • The xa_extract function combines the functionality of
    radix_tree_gang_lookup() and radix_tree_gang_lookup_tagged().
    It extracts entries matching the specified filter into a normal array.

    Signed-off-by: Matthew Wilcox

    Matthew Wilcox
     
  • The xa_for_each iterator allows the user to efficiently walk a range
    of the array, executing the loop body once for each entry in that
    range that matches the filter. This commit also includes xa_find()
    and xa_find_after() which are helper functions for xa_for_each() but
    may also be useful in their own right.

    In the xas family of functions, we have xas_for_each(), xas_find(),
    xas_next_entry(), xas_for_each_tagged(), xas_find_tagged(),
    xas_next_tagged() and xas_pause().

    Signed-off-by: Matthew Wilcox

    Matthew Wilcox
     
  • Like cmpxchg(), xa_cmpxchg will only store to the index if the current
    entry matches the old entry. It returns the current entry, which is
    usually more useful than the errno returned by radix_tree_insert().
    For the users who really only want the errno, the xa_insert() wrapper
    provides a more convenient calling convention.

    Signed-off-by: Matthew Wilcox

    Matthew Wilcox
     
  • xa_store() differs from radix_tree_insert() in that it will overwrite an
    existing element in the array rather than returning an error. This is
    the behaviour which most users want, and those that want more complex
    behaviour generally want to use the xas family of routines anyway.

    For memory allocation, xa_store() will first attempt to request memory
    from the slab allocator; if memory is not immediately available, it will
    drop the xa_lock and allocate memory, keeping a pointer in the xa_state.
    It does not use the per-CPU cache, although those will continue to exist
    until all radix tree users are converted to the xarray.

    This patch also includes xa_erase() and __xa_erase() for a streamlined
    way to store NULL. Since there is no need to allocate memory in order
    to store a NULL in the XArray, we do not need to trouble the user with
    deciding what memory allocation flags to use.

    Signed-off-by: Matthew Wilcox

    Matthew Wilcox
     
  • XArray marks are like the radix tree tags, only slightly more strongly
    typed. They are renamed in order to distinguish them from tagged
    pointers. This commit adds the basic get/set/clear operations.

    Signed-off-by: Matthew Wilcox

    Matthew Wilcox
     
  • The xa_load function brings with it a lot of infrastructure; xa_empty(),
    xa_is_err(), and large chunks of the XArray advanced API that are used
    to implement xa_load.

    As the test-suite demonstrates, it is possible to use the XArray functions
    on a radix tree. The radix tree functions depend on the GFP flags being
    stored in the root of the tree, so it's not possible to use the radix
    tree functions on an XArray.

    Signed-off-by: Matthew Wilcox

    Matthew Wilcox
     
  • This is a direct replacement for struct radix_tree_node. A couple of
    struct members have changed name, so convert those. Use a #define so
    that radix tree users continue to work without change.

    Signed-off-by: Matthew Wilcox
    Reviewed-by: Josef Bacik

    Matthew Wilcox
     
  • This is a direct replacement for struct radix_tree_root. Some of the
    struct members have changed name; convert those, and use a #define so
    that radix_tree users continue to work without change.

    Signed-off-by: Matthew Wilcox
    Reviewed-by: Josef Bacik

    Matthew Wilcox
     

30 Sep, 2018

3 commits

  • Instead of storing a pointer to the slot containing the canonical entry,
    store the offset of the slot. Produces slightly more efficient code
    (~300 bytes) and simplifies the implementation.

    Signed-off-by: Matthew Wilcox
    Reviewed-by: Josef Bacik

    Matthew Wilcox
     
  • Introduce xarray value entries and tagged pointers to replace radix
    tree exceptional entries. This is a slight change in encoding to allow
    the use of an extra bit (we can now store BITS_PER_LONG - 1 bits in a
    value entry). It is also a change in emphasis; exceptional entries are
    intimidating and different. As the comment explains, you can choose
    to store values or pointers in the xarray and they are both first-class
    citizens.

    Signed-off-by: Matthew Wilcox
    Reviewed-by: Josef Bacik

    Matthew Wilcox
     
  • Redirect some older email addresses that are in the git logs.

    Signed-off-by: Matthew Wilcox

    Matthew Wilcox