mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v2] dm ebs: drop dirty bufio state when discarding blocks
@ 2026-06-08 16:06 Samuel Moelius
  2026-06-10 19:54 ` Mikulas Patocka
  0 siblings, 1 reply; 3+ messages in thread
From: Samuel Moelius @ 2026-06-08 16:06 UTC (permalink / raw)
  To: Alasdair Kergon
  Cc: Samuel Moelius, Mike Snitzer, Mikulas Patocka,
	Benjamin Marzinski, open list:DEVICE-MAPPER  (LVM),
	open list

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 <sam.moelius@trailofbits.com>
---
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


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH v2] dm ebs: drop dirty bufio state when discarding blocks
  2026-06-08 16:06 [PATCH v2] dm ebs: drop dirty bufio state when discarding blocks Samuel Moelius
@ 2026-06-10 19:54 ` Mikulas Patocka
  2026-07-02 11:33   ` Samuel Moelius
  0 siblings, 1 reply; 3+ messages in thread
From: Mikulas Patocka @ 2026-06-10 19:54 UTC (permalink / raw)
  To: Samuel Moelius
  Cc: Alasdair Kergon, Mike Snitzer, Benjamin Marzinski,
	open list:DEVICE-MAPPER  (LVM),
	open list

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 <sam.moelius@trailofbits.com>
> ---
> 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
> 


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH v2] dm ebs: drop dirty bufio state when discarding blocks
  2026-06-10 19:54 ` Mikulas Patocka
@ 2026-07-02 11:33   ` Samuel Moelius
  0 siblings, 0 replies; 3+ messages in thread
From: Samuel Moelius @ 2026-07-02 11:33 UTC (permalink / raw)
  To: Mikulas Patocka
  Cc: Alasdair Kergon, Mike Snitzer, Benjamin Marzinski,
	open list:DEVICE-MAPPER (LVM),
	open list

On Wed, Jun 10, 2026 at 3:54 PM Mikulas Patocka <mpatocka@redhat.com> wrote:
>
> Hi
>
> I will accept this (and the other patches) after the upcoming merge window
> ends.

If I am not mistaken, the merge window has closed. Should I resend the patch?

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-07-02 11:33 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-06-08 16:06 [PATCH v2] dm ebs: drop dirty bufio state when discarding blocks Samuel Moelius
2026-06-10 19:54 ` Mikulas Patocka
2026-07-02 11:33   ` Samuel Moelius

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®