All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] pnfs/blocklayout: don't let a READ layout hide written extents
@ 2026-10-30  7:40 ` Daejun Park via B4 Relay
  0 siblings, 0 replies; 3+ messages in thread
From: Daejun Park @ 2026-10-30  7:40 UTC (permalink / raw)
  To: Trond Myklebust, Anna Schumaker
  Cc: Christoph Hellwig, Benjamin Coddington, linux-nfs, Daejun Park

Once a client writes to an INVALID_DATA extent, reads must use it
(RFC 5663, section 2.3.4). A READ layout fetched before LAYOUTCOMMIT
can map the range as NONE_DATA. Lookups check read-only extents first.
The client then reads zeroes until the layout is returned.

Do not add read-only extents over written or READ_WRITE_DATA extents.

Fixes: 8067253c8cc5 ("pnfs/blocklayout: rewrite extent tracking")
Signed-off-by: Daejun Park <daejun7.park@samsung.com>
---
Against next-20261006. extent_tree.c is the same in next-20261029
and in mainline 65ba8f34ec88.

Tested against Linux nfsd on XFS: an O_DIRECT write into a range with
no data, then a read across it, returned zeroes in 12 of 12 runs before
and the written data after. generic/013, 091 and 263 pass.
---
 fs/nfs/blocklayout/extent_tree.c | 27 ++++++++++++++++++++++++++-
 1 file changed, 26 insertions(+), 1 deletion(-)

diff --git a/fs/nfs/blocklayout/extent_tree.c b/fs/nfs/blocklayout/extent_tree.c
index 7393118c42..40a6ab6329 100644
--- a/fs/nfs/blocklayout/extent_tree.c
+++ b/fs/nfs/blocklayout/extent_tree.c
@@ -252,6 +252,28 @@ __ext_tree_remove(struct rb_root *root,
 	return 0;
 }
 
+/*
+ * Return the first extent at or after @start that a new read-only
+ * extent must not cover: an ro extent, or an rw extent before @end
+ * that reads use. An INVALID_DATA extent not yet written to does
+ * not count: reads of it use the ro extent below it (copy-on-write).
+ */
+static struct pnfs_block_extent *
+ext_tree_search_ro(struct pnfs_block_layout *bl, sector_t start, sector_t end)
+{
+	struct pnfs_block_extent *be = __ext_tree_search(&bl->bl_ext_ro, start);
+	struct pnfs_block_extent *rw;
+
+	if (be && be->be_f_offset < end)
+		end = be->be_f_offset;
+	for (rw = __ext_tree_search(&bl->bl_ext_rw, start);
+	     rw && rw->be_f_offset < end; rw = ext_tree_next(rw)) {
+		if (rw->be_state != PNFS_BLOCK_INVALID_DATA || rw->be_tag)
+			return rw;
+	}
+	return be;
+}
+
 int
 ext_tree_insert(struct pnfs_block_layout *bl, struct pnfs_block_extent *new)
 {
@@ -275,7 +297,10 @@ ext_tree_insert(struct pnfs_block_layout *bl, struct pnfs_block_extent *new)
 
 	spin_lock(&bl->bl_ext_lock);
 retry:
-	be = __ext_tree_search(root, new->be_f_offset);
+	if (root == &bl->bl_ext_ro)
+		be = ext_tree_search_ro(bl, new->be_f_offset, ext_f_end(new));
+	else
+		be = __ext_tree_search(root, new->be_f_offset);
 	if (!be || be->be_f_offset >= ext_f_end(new)) {
 		__ext_tree_insert(root, new, true);
 	} else if (new->be_f_offset >= be->be_f_offset) {

---
base-commit: eea3fef32a9cf36abcb5975a5a594e4135a6b026
change-id: 20261030-nfs-bl-ro-cdbf608f4f0d

Best regards,
-- 
Daejun Park <daejun7.park@samsung.com>


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

* [PATCH] pnfs/blocklayout: don't let a READ layout hide written extents
@ 2026-10-30  7:40 ` Daejun Park via B4 Relay
  0 siblings, 0 replies; 3+ messages in thread
From: Daejun Park via B4 Relay @ 2026-10-30  7:40 UTC (permalink / raw)
  To: Trond Myklebust, Anna Schumaker
  Cc: Christoph Hellwig, Benjamin Coddington, linux-nfs, Daejun Park

From: Daejun Park <daejun7.park@samsung.com>

Once a client writes to an INVALID_DATA extent, reads must use it
(RFC 5663, section 2.3.4). A READ layout fetched before LAYOUTCOMMIT
can map the range as NONE_DATA. Lookups check read-only extents first.
The client then reads zeroes until the layout is returned.

Do not add read-only extents over written or READ_WRITE_DATA extents.

Fixes: 8067253c8cc5 ("pnfs/blocklayout: rewrite extent tracking")
Signed-off-by: Daejun Park <daejun7.park@samsung.com>
---
Against next-20261006. extent_tree.c is the same in next-20261029
and in mainline 65ba8f34ec88.

Tested against Linux nfsd on XFS: an O_DIRECT write into a range with
no data, then a read across it, returned zeroes in 12 of 12 runs before
and the written data after. generic/013, 091 and 263 pass.
---
 fs/nfs/blocklayout/extent_tree.c | 27 ++++++++++++++++++++++++++-
 1 file changed, 26 insertions(+), 1 deletion(-)

diff --git a/fs/nfs/blocklayout/extent_tree.c b/fs/nfs/blocklayout/extent_tree.c
index 7393118c42..40a6ab6329 100644
--- a/fs/nfs/blocklayout/extent_tree.c
+++ b/fs/nfs/blocklayout/extent_tree.c
@@ -252,6 +252,28 @@ __ext_tree_remove(struct rb_root *root,
 	return 0;
 }
 
+/*
+ * Return the first extent at or after @start that a new read-only
+ * extent must not cover: an ro extent, or an rw extent before @end
+ * that reads use. An INVALID_DATA extent not yet written to does
+ * not count: reads of it use the ro extent below it (copy-on-write).
+ */
+static struct pnfs_block_extent *
+ext_tree_search_ro(struct pnfs_block_layout *bl, sector_t start, sector_t end)
+{
+	struct pnfs_block_extent *be = __ext_tree_search(&bl->bl_ext_ro, start);
+	struct pnfs_block_extent *rw;
+
+	if (be && be->be_f_offset < end)
+		end = be->be_f_offset;
+	for (rw = __ext_tree_search(&bl->bl_ext_rw, start);
+	     rw && rw->be_f_offset < end; rw = ext_tree_next(rw)) {
+		if (rw->be_state != PNFS_BLOCK_INVALID_DATA || rw->be_tag)
+			return rw;
+	}
+	return be;
+}
+
 int
 ext_tree_insert(struct pnfs_block_layout *bl, struct pnfs_block_extent *new)
 {
@@ -275,7 +297,10 @@ ext_tree_insert(struct pnfs_block_layout *bl, struct pnfs_block_extent *new)
 
 	spin_lock(&bl->bl_ext_lock);
 retry:
-	be = __ext_tree_search(root, new->be_f_offset);
+	if (root == &bl->bl_ext_ro)
+		be = ext_tree_search_ro(bl, new->be_f_offset, ext_f_end(new));
+	else
+		be = __ext_tree_search(root, new->be_f_offset);
 	if (!be || be->be_f_offset >= ext_f_end(new)) {
 		__ext_tree_insert(root, new, true);
 	} else if (new->be_f_offset >= be->be_f_offset) {

---
base-commit: eea3fef32a9cf36abcb5975a5a594e4135a6b026
change-id: 20261030-nfs-bl-ro-cdbf608f4f0d

Best regards,
-- 
Daejun Park <daejun7.park@samsung.com>



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

* Re: [PATCH] pnfs/blocklayout: don't let a READ layout hide written extents
  2026-10-30  7:40 ` Daejun Park via B4 Relay
  (?)
@ 2026-11-03  7:50 ` Christoph Hellwig
  -1 siblings, 0 replies; 3+ messages in thread
From: Christoph Hellwig @ 2026-11-03  7:50 UTC (permalink / raw)
  To: daejun7.park
  Cc: Trond Myklebust, Anna Schumaker, Christoph Hellwig,
	Benjamin Coddington, linux-nfs

Looks good:

Reviewed-by: Christoph Hellwig <hch@lst.de>


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

end of thread, other threads:[~2026-11-03  7:50 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-30  7:40 [PATCH] pnfs/blocklayout: don't let a READ layout hide written extents Daejun Park
2026-10-30  7:40 ` Daejun Park via B4 Relay
2026-11-03  7:50 ` Christoph Hellwig

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.