forked from swarren/WSL2-Linux-Kernel
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
lightnvm: physical block device (pblk) target
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 <matias@cnexlabs.com> Simon A. F. Lund <slund@cnexlabs.com> Young Tack Jin <youngtack.jin@gmail.com> Huaicheng Li <huaicheng@cs.uchicago.edu> Signed-off-by: Javier González <javier@cnexlabs.com> Signed-off-by: Matias Bjørling <matias@cnexlabs.com> Signed-off-by: Jens Axboe <axboe@fb.com>
- Loading branch information
Showing
15 changed files
with
8,044 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
pblk: Physical Block Device Target | ||
================================== | ||
|
||
pblk implements a fully associative, host-based FTL that exposes a traditional | ||
block I/O interface. Its primary responsibilities are: | ||
|
||
- Map logical addresses onto physical addresses (4KB granularity) in a | ||
logical-to-physical (L2P) table. | ||
- Maintain the integrity and consistency of the L2P table as well as its | ||
recovery from normal tear down and power outage. | ||
- Deal with controller- and media-specific constrains. | ||
- Handle I/O errors. | ||
- Implement garbage collection. | ||
- Maintain consistency across the I/O stack during synchronization points. | ||
|
||
For more information please refer to: | ||
|
||
http://lightnvm.io | ||
|
||
which maintains updated FAQs, manual pages, technical documentation, tools, | ||
contacts, etc. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
/* | ||
* Copyright (C) 2016 CNEX Labs | ||
* Initial release: Javier Gonzalez <javier@cnexlabs.com> | ||
* Matias Bjorling <matias@cnexlabs.com> | ||
* | ||
* This program is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU General Public License version | ||
* 2 as published by the Free Software Foundation. | ||
* | ||
* This program is distributed in the hope that it will be useful, but | ||
* WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
* General Public License for more details. | ||
* | ||
* pblk-cache.c - pblk's write cache | ||
*/ | ||
|
||
#include "pblk.h" | ||
|
||
int pblk_write_to_cache(struct pblk *pblk, struct bio *bio, unsigned long flags) | ||
{ | ||
struct pblk_w_ctx w_ctx; | ||
sector_t lba = pblk_get_lba(bio); | ||
unsigned int bpos, pos; | ||
int nr_entries = pblk_get_secs(bio); | ||
int i, ret; | ||
|
||
/* Update the write buffer head (mem) with the entries that we can | ||
* write. The write in itself cannot fail, so there is no need to | ||
* rollback from here on. | ||
*/ | ||
retry: | ||
ret = pblk_rb_may_write_user(&pblk->rwb, bio, nr_entries, &bpos); | ||
if (ret == NVM_IO_REQUEUE) { | ||
io_schedule(); | ||
goto retry; | ||
} | ||
|
||
if (unlikely(!bio_has_data(bio))) | ||
goto out; | ||
|
||
w_ctx.flags = flags; | ||
pblk_ppa_set_empty(&w_ctx.ppa); | ||
|
||
for (i = 0; i < nr_entries; i++) { | ||
void *data = bio_data(bio); | ||
|
||
w_ctx.lba = lba + i; | ||
|
||
pos = pblk_rb_wrap_pos(&pblk->rwb, bpos + i); | ||
pblk_rb_write_entry_user(&pblk->rwb, data, w_ctx, pos); | ||
|
||
bio_advance(bio, PBLK_EXPOSED_PAGE_SIZE); | ||
} | ||
|
||
#ifdef CONFIG_NVM_DEBUG | ||
atomic_long_add(nr_entries, &pblk->inflight_writes); | ||
atomic_long_add(nr_entries, &pblk->req_writes); | ||
#endif | ||
|
||
out: | ||
pblk_write_should_kick(pblk); | ||
return ret; | ||
} | ||
|
||
/* | ||
* On GC the incoming lbas are not necessarily sequential. Also, some of the | ||
* lbas might not be valid entries, which are marked as empty by the GC thread | ||
*/ | ||
int pblk_write_gc_to_cache(struct pblk *pblk, void *data, u64 *lba_list, | ||
unsigned int nr_entries, unsigned int nr_rec_entries, | ||
struct pblk_line *gc_line, unsigned long flags) | ||
{ | ||
struct pblk_w_ctx w_ctx; | ||
unsigned int bpos, pos; | ||
int i, valid_entries; | ||
|
||
/* Update the write buffer head (mem) with the entries that we can | ||
* write. The write in itself cannot fail, so there is no need to | ||
* rollback from here on. | ||
*/ | ||
retry: | ||
if (!pblk_rb_may_write_gc(&pblk->rwb, nr_rec_entries, &bpos)) { | ||
io_schedule(); | ||
goto retry; | ||
} | ||
|
||
w_ctx.flags = flags; | ||
pblk_ppa_set_empty(&w_ctx.ppa); | ||
|
||
for (i = 0, valid_entries = 0; i < nr_entries; i++) { | ||
if (lba_list[i] == ADDR_EMPTY) | ||
continue; | ||
|
||
w_ctx.lba = lba_list[i]; | ||
|
||
pos = pblk_rb_wrap_pos(&pblk->rwb, bpos + valid_entries); | ||
pblk_rb_write_entry_gc(&pblk->rwb, data, w_ctx, gc_line, pos); | ||
|
||
data += PBLK_EXPOSED_PAGE_SIZE; | ||
valid_entries++; | ||
} | ||
|
||
WARN_ONCE(nr_rec_entries != valid_entries, | ||
"pblk: inconsistent GC write\n"); | ||
|
||
#ifdef CONFIG_NVM_DEBUG | ||
atomic_long_add(valid_entries, &pblk->inflight_writes); | ||
atomic_long_add(valid_entries, &pblk->recov_gc_writes); | ||
#endif | ||
|
||
pblk_write_should_kick(pblk); | ||
return NVM_IO_OK; | ||
} |
Oops, something went wrong.