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
> 


Reply via email to