29 Jul, 2016

1 commit

  • copy_page_to_iter_iovec() and copy_page_from_iter_iovec() copy some data
    to userspace or from userspace. These functions have a fast path where
    they map a page using kmap_atomic and a slow path where they use kmap.

    kmap is slower than kmap_atomic, so the fast path is preferred.

    However, on kernels without highmem support, kmap just calls
    page_address, so there is no need to avoid kmap. On kernels without
    highmem support, the fast path just increases code size (and cache
    footprint) and it doesn't improve copy performance in any way.

    This patch enables the fast path only if CONFIG_HIGHMEM is defined.

    Code size reduced by this patch:
    x86 (without highmem) 928
    x86-64 960
    sparc64 848
    alpha 1136
    pa-risc 1200

    [akpm@linux-foundation.org: use IS_ENABLED(), per Andi]
    Link: http://lkml.kernel.org/r/alpine.LRH.2.02.1607221711410.4818@file01.intranet.prod.int.rdu2.redhat.com
    Signed-off-by: Mikulas Patocka
    Cc: Hugh Dickins
    Cc: Michal Hocko
    Cc: Alexander Viro
    Cc: Mel Gorman
    Cc: Johannes Weiner
    Cc: Andi Kleen
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Mikulas Patocka
     

10 Jun, 2016

1 commit

  • bvec has one native/mature iterator for long time, so not
    necessary to use the reinvented wheel for iterating bvecs
    in lib/iov_iter.c.

    Two ITER_BVEC test cases are run:
    - xfstest(-g auto) on loop dio/aio, no regression found
    - swap file works well under extreme stress(stress-ng --all 64 -t
    800 -v), and lots of OOMs are triggerd, and the whole
    system still survives

    Reviewed-by: Christoph Hellwig
    Signed-off-by: Ming Lei
    Tested-by: Hannes Reinecke
    Signed-off-by: Jens Axboe

    Ming Lei
     

26 May, 2016

2 commits

  • Pull vfs iov_iter regression fix from Al Viro:
    "Fix for braino in 'fold checks into iterate_and_advance()'"

    * 'work.iov_iter' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
    do "fold checks into iterate_and_advance()" right

    Linus Torvalds
     
  • the only case when we should skip the iterate_and_advance() guts
    is when nothing's left in the iterator, _not_ just when requested
    amount is 0. Said guts will do nothing in the latter case anyway;
    the problem we tried to deal with in the aforementioned commit is
    that when there's nothing left *and* the amount requested is 0,
    we might end up deferencing one iovec too many; the value we fetch
    from there is discarded in that case, but theoretically it might
    oops if the iovec array ends exactly at the end of page with the
    next page not mapped.

    Bailing out on zero size requested had an unexpected side effect -
    zero-length segment in the beginning of iovec array ended up
    throwing do_loop_readv_writev() into infinite spin; we do not
    advance past the empty segment at all. Reproducer is trivial:
    echo '#include ' >a.c
    echo 'main() {char c; struct iovec v[] = {{&c,0},{&c,1}}; readv(0,v,2);}' >>a.c
    cc a.c && ./a.out

    Al Viro
     

19 May, 2016

1 commit


10 May, 2016

1 commit

  • they are open-coded in all users except iov_iter_advance(), and there
    they wouldn't be a bad idea either - as it is, iov_iter_advance(i, 0)
    ends up dereferencing potentially past the end of iovec array. It
    doesn't do anything with the value it reads, and very unlikely to
    trigger an oops on dereference, but it is not impossible.

    Reported-by: Jiri Slaby
    Reported-by: Takashi Iwai
    Signed-off-by: Al Viro

    Al Viro
     

09 Apr, 2016

1 commit


07 Dec, 2015

2 commits


12 Apr, 2015

2 commits


30 Mar, 2015

1 commit

  • iovec-backed iov_iter instances are assumed to satisfy several properties:
    * no more than UIO_MAXIOV elements in iovec array
    * total size of all ranges is no more than MAX_RW_COUNT
    * all ranges pass access_ok().

    The problem is, invariants of data structures should be established in the
    primitives creating those data structures, not in the code using those
    primitives. And iov_iter_init() violates that principle. For a while we
    managed to get away with that, but once the use of iov_iter started to
    spread, it didn't take long for shit to hit the fan - missed check in
    sys_sendto() had introduced a roothole.

    We _do_ have primitives for importing and validating iovecs (both native and
    compat ones) and those primitives are almost always followed by shoving the
    resulting iovec into iov_iter. Life would be considerably simpler (and safer)
    if we combined those primitives with initializing iov_iter.

    That gives us two new primitives - import_iovec() and compat_import_iovec().
    Calling conventions:
    iovec = iov_array;
    err = import_iovec(direction, uvec, nr_segs,
    ARRAY_SIZE(iov_array), &iovec,
    &iter);
    imports user vector into kernel space (into iov_array if it fits, allocated
    if it doesn't fit or if iovec was NULL), validates it and sets iter up to
    refer to it. On success 0 is returned and allocated kernel copy (or NULL
    if the array had fit into caller-supplied one) is returned via iovec.
    On failure all allocations are undone and -E... is returned. If the total
    size of ranges exceeds MAX_RW_COUNT, the excess is silently truncated.

    compat_import_iovec() expects uvec to be a pointer to user array of compat_iovec;
    otherwise it's identical to import_iovec().

    Finally, import_single_range() sets iov_iter backed by single-element iovec
    covering a user-supplied range -

    err = import_single_range(direction, address, size, iovec, &iter);

    does validation and sets iter up. Again, size in excess of MAX_RW_COUNT gets
    silently truncated.

    Next commits will be switching the things up to use of those and reducing
    the amount of iov_iter_init() instances.

    Signed-off-by: Al Viro

    Al Viro
     

18 Feb, 2015

1 commit