Hi I will accept this (and the other patches) after the upcoming merge window ends.
Mikulas On Mon, 8 Jun 2026, Samuel Moelius wrote: > dm-ebs can discard a block while a dirty dm-bufio buffer for the same > block is still cached. If that buffer is later written back, stale data > can be written over the discarded state. > > That resurrects data that userspace explicitly discarded and breaks the > expected discard semantics of the target. > > Flush pending dirty buffers before processing a following discard, then > forget the matching bufio state and issue the discard. Keep writeback > errors separate from the discard result so a flush failure is reported > to the write bios that dirtied the buffers, while the discard bio > reports only the discard operation's own status. > > Assisted-by: Codex:gpt-5.5-cyber-preview > Signed-off-by: Samuel Moelius <[email protected]> > --- > Changes in v2 > - fix how dirty bios are handled and how errors are reported > > drivers/md/dm-ebs-target.c | 20 +++++++++++++++----- > 1 file changed, 15 insertions(+), 5 deletions(-) > > diff --git a/drivers/md/dm-ebs-target.c b/drivers/md/dm-ebs-target.c > index 1e52bde48b91..5bdd1bf6c206 100644 > --- a/drivers/md/dm-ebs-target.c > +++ b/drivers/md/dm-ebs-target.c > @@ -176,8 +176,8 @@ static void __ebs_forget_bio(struct ebs_c *ec, struct bio > *bio) > /* Worker function to process incoming bios. */ > static void __ebs_process_bios(struct work_struct *ws) > { > - int r; > - bool write = false; > + int r, rr, write_r = 0; > + bool dirty = false; > sector_t block1, block2; > struct ebs_c *ec = container_of(ws, struct ebs_c, ws); > struct bio *bio; > @@ -209,9 +209,15 @@ static void __ebs_process_bios(struct work_struct *ws) > if (bio_op(bio) == REQ_OP_READ) > r = __ebs_rw_bio(ec, REQ_OP_READ, bio); > else if (bio_op(bio) == REQ_OP_WRITE) { > - write = true; > r = __ebs_rw_bio(ec, REQ_OP_WRITE, bio); > + dirty = true; > } else if (bio_op(bio) == REQ_OP_DISCARD) { > + if (dirty) { > + rr = dm_bufio_write_dirty_buffers(ec->bufio); > + dirty = false; > + if (rr && !write_r) > + write_r = rr; > + } > __ebs_forget_bio(ec, bio); > r = __ebs_discard_bio(ec, bio); > } > @@ -224,11 +230,15 @@ static void __ebs_process_bios(struct work_struct *ws) > * We write dirty buffers after processing I/O on them > * but before we endio thus addressing REQ_FUA/REQ_SYNC. > */ > - r = write ? dm_bufio_write_dirty_buffers(ec->bufio) : 0; > + if (dirty) { > + r = dm_bufio_write_dirty_buffers(ec->bufio); > + if (r && !write_r) > + write_r = r; > + } > > while ((bio = bio_list_pop(&bios))) { > /* Any other request is endioed. */ > - if (unlikely(r && bio_op(bio) == REQ_OP_WRITE)) > + if (unlikely(write_r && bio_op(bio) == REQ_OP_WRITE)) > bio_io_error(bio); > else > bio_endio(bio); > -- > 2.43.0 >

