20 Dec, 2017

1 commit

  • [ Upstream commit bd432417681a224d9fa4a9d43be7d4edc82135b2 ]

    pblk uses an internal page mempool for allocating pages on internal
    bios. The main two users of this memory pool are partial reads (reads
    with some sectors in cache and some on media) and padded writes, which
    need to add dummy pages to an existing bio already containing valid
    data (and with a large enough bioset allocated). In both cases, the
    maximum number of pages per bio is defined by the maximum number of
    physical sectors supported by the underlying device.

    This patch fixes a bad mempool allocation, where the min_nr of elements
    on the pool was fixed (to 16), which is lower than the maximum number
    of sectors supported by NVMe (as of the time for this patch). Instead,
    use the maximum number of allowed sectors reported by the device.

    Reported-by: Jens Axboe
    Signed-off-by: Javier González
    Signed-off-by: Matias Bjørling
    Signed-off-by: Jens Axboe
    Signed-off-by: Sasha Levin
    Signed-off-by: Greg Kroah-Hartman

    Javier González
     

28 Jul, 2017

1 commit

  • When a lba either hits the cache or corresponds to an empty entry in the
    L2P table, we need to advance the bio according to the position in which
    the lba is located. Otherwise, we will copy data in the wrong page, thus
    causing data corruption for the application.

    In case of a cache hit, we assumed that bio->bi_iter.bi_idx would
    contain the correct index, but this is no necessarily true. Instead, use
    the local bio advance counter and iterator. This guarantees that lbas
    hitting the cache are copied into the right bv_page.

    In case of an empty L2P entry, we omitted to advance the bio. In the
    cases when the same I/O also contains a cache hit, data corresponding
    to this lba will be copied to the wrong bv_page. Fix this by advancing
    the bio as we do in the case of a cache hit.

    Fixes: a4bd217b4326 lightnvm: physical block device (pblk) target

    Signed-off-by: Javier González
    Signed-off-by: Jens Axboe

    Javier González
     

08 Jul, 2017

1 commit


01 Jul, 2017

3 commits

  • When a read is directed to the cache, we risk that the lba has been
    updated during the time we made the L2P table lookup and the time we are
    actually reading form the cache. We intentionally not hold the L2P lock
    not to block other threads.

    While strict ordering is not a guarantee at this level (unless REQ_FLUSH
    has been previously issued), we have experience that some databases that
    have recently implemented direct I/O support, issue metadata reads very
    close to the writes, without issuing a fsync in the middle. An easy way
    to support them while they is to make an extra effort and check the L2P
    map right before reading the cache.

    Signed-off-by: Javier González
    Signed-off-by: Matias Bjørling
    Signed-off-by: Jens Axboe

    Javier González
     
  • When removing a pblk instance, pad the current line using asynchronous
    I/O. This reduces the removal time from ~1 minute in the worst case to a
    couple of seconds.

    Signed-off-by: Javier González
    Signed-off-by: Matias Bjørling
    Signed-off-by: Jens Axboe

    Javier González
     
  • For now, we allocate a per I/O buffer for GC data. Since the potential
    size of the buffer is 256KB and GC is not in the fast path, do this
    allocation with vmalloc. This puts lets pressure on the memory
    allocator at no performance cost.

    Signed-off-by: Javier González
    Signed-off-by: Matias Bjørling
    Signed-off-by: Jens Axboe

    Javier González
     

27 Jun, 2017

11 commits

  • Due to user writes being decoupled from media writes because of the need
    of an intermediate write buffer, irrecoverable media write errors lead
    to pblk stalling; user writes fill up the buffer and end up in an
    infinite retry loop.

    In order to let user writes fail gracefully, it is necessary for pblk to
    keep track of its own internal state and prevent further writes from
    being placed into the write buffer.

    This patch implements a state machine to keep track of internal errors
    and, in case of failure, fail further user writes in an standard way.
    Depending on the type of error, pblk will do its best to persist
    buffered writes (which are already acknowledged) and close down on a
    graceful manner. This way, data might be recovered by re-instantiating
    pblk. Such state machine paves out the way for a state-based FTL log.

    Signed-off-by: Javier González
    Signed-off-by: Matias Bjørling
    Signed-off-by: Jens Axboe

    Javier González
     
  • Make constants to define sizes for internal mempools and workqueues. In
    this process, adjust the values to be more meaningful given the internal
    constrains of the FTL. In order to do this for workqueues, separate the
    current auxiliary workqueue into two dedicated workqueues to manage
    lines being closed and bad blocks.

    Signed-off-by: Javier González
    Signed-off-by: Matias Bjørling
    Signed-off-by: Jens Axboe

    Javier González
     
  • At the moment, in order to get enough read parallelism, we have recycled
    several lines at the same time. This approach has proven not to work
    well when reaching capacity, since we end up mixing valid data from all
    lines, thus not maintaining a sustainable free/recycled line ratio.

    The new design, relies on a two level workqueue mechanism. In the first
    level, we read the metadata for a number of lines based on the GC list
    they reside on (this is governed by the number of valid sectors in each
    line). In the second level, we recycle a single line at a time. Here, we
    issue reads in parallel, while a single GC write thread places data in
    the write buffer. This design allows to (i) only move data from one line
    at a time, thus maintaining a sane free/recycled ration and (ii)
    maintain the GC writer busy with recycled data.

    Signed-off-by: Javier González
    Signed-off-by: Matias Bjørling
    Signed-off-by: Jens Axboe

    Javier González
     
  • smeta size will always be suitable for a kmalloc allocation. Simplify
    the code and leave the vmalloc fallback only for emeta, where the pblk
    configuration has an impact.

    Signed-off-by: Javier González
    Signed-off-by: Matias Bjørling
    Signed-off-by: Jens Axboe

    Javier González
     
  • If a read request is sequential and its size aligns with a
    multi-plane page size, use the multi-plane hint to process the I/O in
    parallel in the controller.

    Signed-off-by: Javier González
    Signed-off-by: Matias Bjørling
    Signed-off-by: Jens Axboe

    Javier González
     
  • After refactoring the metadata path, the backpointer controlling
    synced I/Os in a line becomes unnecessary; metadata is scheduled
    on the write thread, thus we know when the end of the line is reached
    and act on it directly.

    Signed-off-by: Javier González
    Signed-off-by: Matias Bjørling
    Signed-off-by: Jens Axboe

    Javier González
     
  • At the moment, line metadata is persisted on a separate work queue, that
    is kicked each time that a line is closed. The assumption when designing
    this was that freeing the write thread from creating a new write request
    was better than the potential impact of writes colliding on the media
    (user I/O and metadata I/O). Experimentation has proven that this
    assumption is wrong; collision can cause up to 25% of bandwidth and
    introduce long tail latencies on the write thread, which potentially
    cause user write threads to spend more time spinning to get a free entry
    on the write buffer.

    This patch moves the metadata logic to the write thread. When a line is
    closed, remaining metadata is written in memory and is placed on a
    metadata queue. The write thread then takes the metadata corresponding
    to the previous line, creates the write request and schedules it to
    minimize collisions on the media. Using this approach, we see that we
    can saturate the media's bandwidth, which helps reducing both write
    latencies and the spinning time for user writer threads.

    Signed-off-by: Javier González
    Signed-off-by: Matias Bjørling
    Signed-off-by: Jens Axboe

    Javier González
     
  • Read requests allocate some extra memory to store its per I/O context.
    Instead of requiring yet another memory pool for other type of requests,
    generalize this context allocation (and change naming accordingly).

    Signed-off-by: Javier González
    Signed-off-by: Matias Bjørling
    Signed-off-by: Jens Axboe

    Javier González
     
  • Erase I/Os are scheduled with the following goals in mind: (i) minimize
    LUNs collisions with write I/Os, and (ii) even out the price of erasing
    on every write, instead of putting all the burden on when garbage
    collection runs. This works well on the current design, but is specific
    to the default mapping algorithm.

    This patch generalizes the erase path so that other mapping algorithms
    can select an arbitrary line to be erased instead. It also gets rid of
    the erase semaphore since it creates jittering for user writes.

    Signed-off-by: Javier González
    Signed-off-by: Matias Bjørling
    Signed-off-by: Jens Axboe

    Javier González
     
  • Allow to configure the number of maximum sectors per write command
    through sysfs. This makes it easier to tune write command sizes for
    different controller configurations.

    Signed-off-by: Javier González
    Signed-off-by: Matias Bjørling
    Signed-off-by: Jens Axboe

    Javier González
     
  • Add a new debug counter to measure cache hits on the read path

    Signed-off-by: Javier González
    Signed-off-by: Matias Bjørling
    Signed-off-by: Jens Axboe

    Javier González
     

19 Jun, 2017

1 commit

  • pblk_submit_read() uses bio_clone_bioset() but doesn't change the
    io_vec, so bio_clone_fast() is a better choice.

    It also uses fs_bio_set which is intended for filesystems. Using it
    in a device driver can deadlock.
    So allocate a new bioset, and and use bio_clone_fast().

    Reviewed-by: Christoph Hellwig
    Reviewed-by: Javier González
    Tested-by: Javier González
    Signed-off-by: NeilBrown
    Signed-off-by: Jens Axboe

    NeilBrown
     

24 Apr, 2017

1 commit

  • When block erases fail, these blocks are marked bad. The number of valid
    blocks in the line was not updated, which could cause an infinite loop
    on the erase path.

    Fix this atomic counter and, in order to avoid taking an irq lock on the
    interrupt context, make the erase counters atomic too.

    Also, in the case that a significant number of blocks become bad in a
    line, the result is the double shared metadata buffer (emeta) to stop
    the pipeline until all metadata is flushed to the media. Increase the
    number of metadata lines from 2 to 4 to avoid this case.

    Fixes: a4bd217b4326 "lightnvm: physical block device (pblk) target"

    Signed-off-by: Javier González
    Reviewed-by: Matias Bjørling
    Signed-off-by: Jens Axboe

    Javier González
     

20 Apr, 2017

1 commit

  • The driver uses both u64 and sector_t to refer to offsets, and assigns between the
    two. This causes one harmless warning when sector_t is 32-bit:

    drivers/lightnvm/pblk-rb.c: In function 'pblk_rb_write_entry_gc':
    include/linux/lightnvm.h:215:20: error: large integer implicitly truncated to unsigned type [-Werror=overflow]
    drivers/lightnvm/pblk-rb.c:324:22: note: in expansion of macro 'ADDR_EMPTY'

    As the driver is already doing this inconsistently, changing the type
    won't make it worse and is an easy way to avoid the warning.

    Fixes: a4bd217b4326 ("lightnvm: physical block device (pblk) target")
    Signed-off-by: Arnd Bergmann
    Signed-off-by: Jens Axboe

    Arnd Bergmann
     

17 Apr, 2017

1 commit

  • This patch introduces pblk, a host-side translation layer for
    Open-Channel SSDs to expose them like block devices. The translation
    layer allows data placement decisions, and I/O scheduling to be
    managed by the host, enabling users to optimize the SSD for their
    specific workloads.

    An open-channel SSD has a set of LUNs (parallel units) and a
    collection of blocks. Each block can be read in any order, but
    writes must be sequential. Writes may also fail, and if a block
    requires it, must also be reset before new writes can be
    applied.

    To manage the constraints, pblk maintains a logical to
    physical address (L2P) table, write cache, garbage
    collection logic, recovery scheme, and logic to rate-limit
    user I/Os versus garbage collection I/Os.

    The L2P table is fully-associative and manages sectors at a
    4KB granularity. Pblk stores the L2P table in two places, in
    the out-of-band area of the media and on the last page of a
    line. In the cause of a power failure, pblk will perform a
    scan to recover the L2P table.

    The user data is organized into lines. A line is data
    striped across blocks and LUNs. The lines enable the host to
    reduce the amount of metadata to maintain besides the user
    data and makes it easier to implement RAID or erasure coding
    in the future.

    pblk implements multi-tenant support and can be instantiated
    multiple times on the same drive. Each instance owns a
    portion of the SSD - both regarding I/O bandwidth and
    capacity - providing I/O isolation for each case.

    Finally, pblk also exposes a sysfs interface that allows
    user-space to peek into the internals of pblk. The interface
    is available at /dev/block/*/pblk/ where * is the block
    device name exposed.

    This work also contains contributions from:
    Matias Bjørling
    Simon A. F. Lund
    Young Tack Jin
    Huaicheng Li

    Signed-off-by: Javier González
    Signed-off-by: Matias Bjørling
    Signed-off-by: Jens Axboe

    Javier González