Commit 533657c1 authored by Hans Holmberg's avatar Hans Holmberg Committed by Jens Axboe

lightnvm: pblk: clear flush point on completed writes

Move completion of syncs and clearing of flush points to the
write completion path - this ensures that the data has been
comitted to the media before completing bios containing syncs.
Signed-off-by: default avatarHans Holmberg <hans.holmberg@cnexlabs.com>
Signed-off-by: default avatarJavier González <javier@cnexlabs.com>
Signed-off-by: default avatarMatias Bjørling <m@bjorling.me>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 8154d296
...@@ -353,17 +353,17 @@ static int pblk_rb_flush_point_set(struct pblk_rb *rb, struct bio *bio, ...@@ -353,17 +353,17 @@ static int pblk_rb_flush_point_set(struct pblk_rb *rb, struct bio *bio,
unsigned int pos) unsigned int pos)
{ {
struct pblk_rb_entry *entry; struct pblk_rb_entry *entry;
unsigned int subm, flush_point; unsigned int sync, flush_point;
subm = READ_ONCE(rb->subm); sync = READ_ONCE(rb->sync);
if (pos == sync)
return 0;
#ifdef CONFIG_NVM_DEBUG #ifdef CONFIG_NVM_DEBUG
atomic_inc(&rb->inflight_flush_point); atomic_inc(&rb->inflight_flush_point);
#endif #endif
if (pos == subm)
return 0;
flush_point = (pos == 0) ? (rb->nr_entries - 1) : (pos - 1); flush_point = (pos == 0) ? (rb->nr_entries - 1) : (pos - 1);
entry = &rb->entries[flush_point]; entry = &rb->entries[flush_point];
...@@ -606,22 +606,6 @@ unsigned int pblk_rb_read_to_bio(struct pblk_rb *rb, struct nvm_rq *rqd, ...@@ -606,22 +606,6 @@ unsigned int pblk_rb_read_to_bio(struct pblk_rb *rb, struct nvm_rq *rqd,
return NVM_IO_ERR; return NVM_IO_ERR;
} }
if (flags & PBLK_FLUSH_ENTRY) {
unsigned int flush_point;
flush_point = READ_ONCE(rb->flush_point);
if (flush_point == pos) {
/* Protect flush points */
smp_store_release(&rb->flush_point,
EMPTY_ENTRY);
}
flags &= ~PBLK_FLUSH_ENTRY;
#ifdef CONFIG_NVM_DEBUG
atomic_dec(&rb->inflight_flush_point);
#endif
}
flags &= ~PBLK_WRITTEN_DATA; flags &= ~PBLK_WRITTEN_DATA;
flags |= PBLK_SUBMITTED_ENTRY; flags |= PBLK_SUBMITTED_ENTRY;
...@@ -731,15 +715,24 @@ void pblk_rb_sync_end(struct pblk_rb *rb, unsigned long *flags) ...@@ -731,15 +715,24 @@ void pblk_rb_sync_end(struct pblk_rb *rb, unsigned long *flags)
unsigned int pblk_rb_sync_advance(struct pblk_rb *rb, unsigned int nr_entries) unsigned int pblk_rb_sync_advance(struct pblk_rb *rb, unsigned int nr_entries)
{ {
unsigned int sync; unsigned int sync, flush_point;
unsigned int i;
lockdep_assert_held(&rb->s_lock); lockdep_assert_held(&rb->s_lock);
sync = READ_ONCE(rb->sync); sync = READ_ONCE(rb->sync);
flush_point = READ_ONCE(rb->flush_point);
for (i = 0; i < nr_entries; i++) if (flush_point != EMPTY_ENTRY) {
sync = (sync + 1) & (rb->nr_entries - 1); unsigned int secs_to_flush;
secs_to_flush = pblk_rb_ring_count(flush_point, sync,
rb->nr_entries);
if (secs_to_flush < nr_entries) {
/* Protect flush points */
smp_store_release(&rb->flush_point, EMPTY_ENTRY);
}
}
sync = (sync + nr_entries) & (rb->nr_entries - 1);
/* Protect from counts */ /* Protect from counts */
smp_store_release(&rb->sync, sync); smp_store_release(&rb->sync, sync);
...@@ -747,22 +740,27 @@ unsigned int pblk_rb_sync_advance(struct pblk_rb *rb, unsigned int nr_entries) ...@@ -747,22 +740,27 @@ unsigned int pblk_rb_sync_advance(struct pblk_rb *rb, unsigned int nr_entries)
return sync; return sync;
} }
/* Calculate how many sectors to submit up to the current flush point. */
unsigned int pblk_rb_flush_point_count(struct pblk_rb *rb) unsigned int pblk_rb_flush_point_count(struct pblk_rb *rb)
{ {
unsigned int subm, flush_point; unsigned int subm, sync, flush_point;
unsigned int count; unsigned int submitted, to_flush;
/* Protect flush points */ /* Protect flush points */
flush_point = smp_load_acquire(&rb->flush_point); flush_point = smp_load_acquire(&rb->flush_point);
if (flush_point == EMPTY_ENTRY) if (flush_point == EMPTY_ENTRY)
return 0; return 0;
/* Protect syncs */
sync = smp_load_acquire(&rb->sync);
subm = READ_ONCE(rb->subm); subm = READ_ONCE(rb->subm);
submitted = pblk_rb_ring_count(subm, sync, rb->nr_entries);
/* The sync point itself counts as a sector to sync */ /* The sync point itself counts as a sector to sync */
count = pblk_rb_ring_count(flush_point, subm, rb->nr_entries) + 1; to_flush = pblk_rb_ring_count(flush_point, sync, rb->nr_entries) + 1;
return count; return (submitted < to_flush) ? (to_flush - submitted) : 0;
} }
/* /*
......
...@@ -21,13 +21,28 @@ static unsigned long pblk_end_w_bio(struct pblk *pblk, struct nvm_rq *rqd, ...@@ -21,13 +21,28 @@ static unsigned long pblk_end_w_bio(struct pblk *pblk, struct nvm_rq *rqd,
struct pblk_c_ctx *c_ctx) struct pblk_c_ctx *c_ctx)
{ {
struct bio *original_bio; struct bio *original_bio;
struct pblk_rb *rwb = &pblk->rwb;
unsigned long ret; unsigned long ret;
int i; int i;
for (i = 0; i < c_ctx->nr_valid; i++) { for (i = 0; i < c_ctx->nr_valid; i++) {
struct pblk_w_ctx *w_ctx; struct pblk_w_ctx *w_ctx;
int pos = c_ctx->sentry + i;
int flags;
w_ctx = pblk_rb_w_ctx(rwb, pos);
flags = READ_ONCE(w_ctx->flags);
if (flags & PBLK_FLUSH_ENTRY) {
flags &= ~PBLK_FLUSH_ENTRY;
/* Release flags on context. Protect from writes */
smp_store_release(&w_ctx->flags, flags);
#ifdef CONFIG_NVM_DEBUG
atomic_dec(&rwb->inflight_flush_point);
#endif
}
w_ctx = pblk_rb_w_ctx(&pblk->rwb, c_ctx->sentry + i);
while ((original_bio = bio_list_pop(&w_ctx->bios))) while ((original_bio = bio_list_pop(&w_ctx->bios)))
bio_endio(original_bio); bio_endio(original_bio);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment