The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [PATCH 1/2] 9p: use kvzalloc for readdir buffer
@ 2026-04-16  7:26 Pierre Barre
  0 siblings, 0 replies; 5+ messages in thread
From: Pierre Barre @ 2026-04-16  7:26 UTC (permalink / raw)
  To: ericvh, lucho, asmadeus; +Cc: linux_oss, v9fs, linux-kernel, Pierre Barre

The readdir buffer is sized to msize, so kzalloc() can fail under
fragmentation with a page allocation failure in v9fs_alloc_rdir_buf()
/ v9fs_dir_readdir_dotl().

The buffer is only a response sink and is never pack_sg_list()'d,
so kvzalloc() is safe for all transports, unlike the fcall buffers
fixed in e21d451a82f3.

Signed-off-by: Pierre Barre <pierre@barre.sh>
---
 fs/9p/vfs_dir.c | 2 +-
 net/9p/client.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c
index af7f72abbb76..487c177aae38 100644
--- a/fs/9p/vfs_dir.c
+++ b/fs/9p/vfs_dir.c
@@ -70,7 +70,7 @@ static struct p9_rdir *v9fs_alloc_rdir_buf(struct file *filp, int buflen)
 	struct p9_fid *fid = filp->private_data;
 
 	if (!fid->rdir)
-		fid->rdir = kzalloc(sizeof(struct p9_rdir) + buflen, GFP_KERNEL);
+		fid->rdir = kvzalloc(sizeof(struct p9_rdir) + buflen, GFP_KERNEL);
 	return fid->rdir;
 }
 
diff --git a/net/9p/client.c b/net/9p/client.c
index f60d1d041adb..6d9b9054841e 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -765,7 +765,7 @@ static void p9_fid_destroy(struct p9_fid *fid)
 	spin_lock_irqsave(&clnt->lock, flags);
 	idr_remove(&clnt->fids, fid->fid);
 	spin_unlock_irqrestore(&clnt->lock, flags);
-	kfree(fid->rdir);
+	kvfree(fid->rdir);
 	kfree(fid);
 }
 
-- 
2.51.0


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

* [PATCH 1/2] 9p: use kvzalloc for readdir buffer
@ 2026-05-12 13:20 Pierre Barre
  2026-05-12 13:20 ` [PATCH 2/2] 9p: invalidate readdir buffer on seek Pierre Barre
  2026-05-19 12:28 ` [PATCH 1/2] 9p: use kvzalloc for readdir buffer Dominique Martinet
  0 siblings, 2 replies; 5+ messages in thread
From: Pierre Barre @ 2026-05-12 13:20 UTC (permalink / raw)
  To: Eric Van Hensbergen, Latchesar Ionkov, Dominique Martinet
  Cc: Christian Schoenebeck, David Laight, v9fs, linux-kernel,
	Pierre Barre

The readdir buffer is sized to msize, so kzalloc() can fail under
fragmentation with a page allocation failure in v9fs_alloc_rdir_buf()
/ v9fs_dir_readdir_dotl().

The buffer is only a response sink and is never pack_sg_list()'d,
so kvzalloc() is safe for all transports, unlike the fcall buffers
fixed in e21d451a82f3 ("9p: Use kvmalloc for message buffers on
supported transports").

Signed-off-by: Pierre Barre <pierre@barre.sh>
---
 fs/9p/vfs_dir.c | 2 +-
 net/9p/client.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c
index e0d34e4e9076..e82f60c1c854 100644
--- a/fs/9p/vfs_dir.c
+++ b/fs/9p/vfs_dir.c
@@ -70,7 +70,7 @@ static struct p9_rdir *v9fs_alloc_rdir_buf(struct file *filp, int buflen)
 	struct p9_fid *fid = filp->private_data;
 
 	if (!fid->rdir)
-		fid->rdir = kzalloc(sizeof(struct p9_rdir) + buflen, GFP_KERNEL);
+		fid->rdir = kvzalloc(sizeof(struct p9_rdir) + buflen, GFP_KERNEL);
 	return fid->rdir;
 }
 
diff --git a/net/9p/client.c b/net/9p/client.c
index f0dcf252af7e..b7d947910037 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -765,7 +765,7 @@ static void p9_fid_destroy(struct p9_fid *fid)
 	spin_lock_irqsave(&clnt->lock, flags);
 	idr_remove(&clnt->fids, fid->fid);
 	spin_unlock_irqrestore(&clnt->lock, flags);
-	kfree(fid->rdir);
+	kvfree(fid->rdir);
 	kfree(fid);
 }
 
-- 
2.51.0


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

* [PATCH 2/2] 9p: invalidate readdir buffer on seek
  2026-05-12 13:20 [PATCH 1/2] 9p: use kvzalloc for readdir buffer Pierre Barre
@ 2026-05-12 13:20 ` Pierre Barre
  2026-05-19 12:28 ` [PATCH 1/2] 9p: use kvzalloc for readdir buffer Dominique Martinet
  1 sibling, 0 replies; 5+ messages in thread
From: Pierre Barre @ 2026-05-12 13:20 UTC (permalink / raw)
  To: Eric Van Hensbergen, Latchesar Ionkov, Dominique Martinet
  Cc: Christian Schoenebeck, David Laight, v9fs, linux-kernel,
	Pierre Barre

The per-fid readdir buffer (fid->rdir) is populated lazily and only
refilled when fully drained (rdir->head == rdir->tail). userspace
lseek() on a directory fd updates file->f_pos via generic_file_llseek()
but does not touch the cached buffer, so the next getdents() iterates
the stale cache and emits entries from the previous position instead
of the one the caller asked for.

Track the file position the cached data corresponds to in
struct p9_rdir, and drop the cache on entry to iterate_shared when it
no longer matches ctx->pos. The 9p protocol's Tread/Treaddir already
take an arbitrary offset on every request, so a refill at the new
position is always legal; no .llseek override or seek restriction is
needed.

Reported-by: Pierre Barre <pierre@barre.sh>
Link: https://lore.kernel.org/v9fs/496d10b9-40fe-4f81-8014-37497c37ff63@app.fastmail.com/
Signed-off-by: Pierre Barre <pierre@barre.sh>
---
 fs/9p/vfs_dir.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c
index e82f60c1c854..323f85352f6a 100644
--- a/fs/9p/vfs_dir.c
+++ b/fs/9p/vfs_dir.c
@@ -27,6 +27,7 @@
  * struct p9_rdir - readdir accounting
  * @head: start offset of current dirread buffer
  * @tail: end offset of current dirread buffer
+ * @offset: file position the data at @head corresponds to
  * @buf: dirread buffer
  *
  * private structure for keeping track of readdir
@@ -36,6 +37,7 @@
 struct p9_rdir {
 	int head;
 	int tail;
+	loff_t offset;
 	uint8_t buf[];
 };
 
@@ -102,6 +104,9 @@ static int v9fs_dir_readdir(struct file *file, struct dir_context *ctx)
 	kvec.iov_base = rdir->buf;
 	kvec.iov_len = buflen;
 
+	if (rdir->head < rdir->tail && rdir->offset != ctx->pos)
+		rdir->head = rdir->tail = 0;
+
 	while (1) {
 		if (rdir->tail == rdir->head) {
 			struct iov_iter to;
@@ -117,6 +122,7 @@ static int v9fs_dir_readdir(struct file *file, struct dir_context *ctx)
 
 			rdir->head = 0;
 			rdir->tail = n;
+			rdir->offset = ctx->pos;
 		}
 		while (rdir->head < rdir->tail) {
 			err = p9stat_read(fid->clnt, rdir->buf + rdir->head,
@@ -134,6 +140,7 @@ static int v9fs_dir_readdir(struct file *file, struct dir_context *ctx)
 
 			rdir->head += err;
 			ctx->pos += err;
+			rdir->offset = ctx->pos;
 		}
 	}
 }
@@ -161,6 +168,9 @@ static int v9fs_dir_readdir_dotl(struct file *file, struct dir_context *ctx)
 	if (!rdir)
 		return -ENOMEM;
 
+	if (rdir->head < rdir->tail && rdir->offset != ctx->pos)
+		rdir->head = rdir->tail = 0;
+
 	while (1) {
 		if (rdir->tail == rdir->head) {
 			err = p9_client_readdir(fid, rdir->buf, buflen,
@@ -170,6 +180,7 @@ static int v9fs_dir_readdir_dotl(struct file *file, struct dir_context *ctx)
 
 			rdir->head = 0;
 			rdir->tail = err;
+			rdir->offset = ctx->pos;
 		}
 
 		while (rdir->head < rdir->tail) {
@@ -190,6 +201,7 @@ static int v9fs_dir_readdir_dotl(struct file *file, struct dir_context *ctx)
 
 			ctx->pos = curdirent.d_off;
 			rdir->head += err;
+			rdir->offset = ctx->pos;
 		}
 	}
 }
-- 
2.51.0


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

* Re: [PATCH 1/2] 9p: use kvzalloc for readdir buffer
  2026-05-12 13:20 [PATCH 1/2] 9p: use kvzalloc for readdir buffer Pierre Barre
  2026-05-12 13:20 ` [PATCH 2/2] 9p: invalidate readdir buffer on seek Pierre Barre
@ 2026-05-19 12:28 ` Dominique Martinet
  2026-05-19 13:01   ` Pierre Barre
  1 sibling, 1 reply; 5+ messages in thread
From: Dominique Martinet @ 2026-05-19 12:28 UTC (permalink / raw)
  To: Pierre Barre
  Cc: Eric Van Hensbergen, Latchesar Ionkov, Christian Schoenebeck,
	David Laight, v9fs, linux-kernel

Pierre Barre wrote on Tue, May 12, 2026 at 01:20:31PM +0000:
> The readdir buffer is sized to msize, so kzalloc() can fail under
> fragmentation with a page allocation failure in v9fs_alloc_rdir_buf()
> / v9fs_dir_readdir_dotl().
> 
> The buffer is only a response sink and is never pack_sg_list()'d,
> so kvzalloc() is safe for all transports, unlike the fcall buffers
> fixed in e21d451a82f3 ("9p: Use kvmalloc for message buffers on
> supported transports").

Thanks, I need to run some tests but picked both patchs up for testing
When Time Allows before pushing to -next;
I think they're sane enough in this version.

-- 
Dominique

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

* Re: [PATCH 1/2] 9p: use kvzalloc for readdir buffer
  2026-05-19 12:28 ` [PATCH 1/2] 9p: use kvzalloc for readdir buffer Dominique Martinet
@ 2026-05-19 13:01   ` Pierre Barre
  0 siblings, 0 replies; 5+ messages in thread
From: Pierre Barre @ 2026-05-19 13:01 UTC (permalink / raw)
  To: asmadeus
  Cc: Eric Van Hensbergen, Latchesar Ionkov, Christian Schoenebeck,
	David Laight, v9fs, linux-kernel

Thanks!

On Tue, May 19, 2026, at 14:28, Dominique Martinet wrote:
> Pierre Barre wrote on Tue, May 12, 2026 at 01:20:31PM +0000:
>> The readdir buffer is sized to msize, so kzalloc() can fail under
>> fragmentation with a page allocation failure in v9fs_alloc_rdir_buf()
>> / v9fs_dir_readdir_dotl().
>> 
>> The buffer is only a response sink and is never pack_sg_list()'d,
>> so kvzalloc() is safe for all transports, unlike the fcall buffers
>> fixed in e21d451a82f3 ("9p: Use kvmalloc for message buffers on
>> supported transports").
>
> Thanks, I need to run some tests but picked both patchs up for testing
> When Time Allows before pushing to -next;
> I think they're sane enough in this version.
>
> -- 
> Dominique

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

end of thread, other threads:[~2026-05-19 13:02 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-12 13:20 [PATCH 1/2] 9p: use kvzalloc for readdir buffer Pierre Barre
2026-05-12 13:20 ` [PATCH 2/2] 9p: invalidate readdir buffer on seek Pierre Barre
2026-05-19 12:28 ` [PATCH 1/2] 9p: use kvzalloc for readdir buffer Dominique Martinet
2026-05-19 13:01   ` Pierre Barre
  -- strict thread matches above, loose matches on Subject: below --
2026-04-16  7:26 Pierre Barre

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