Re: [PATCH] 9p: use kvzalloc for readdir buffer
"Pierre Barre" <[email protected]> Wed, 15 Apr 2026 11:27:21 +0200
| Newsgroups | dev.linux.lists.v9fs,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
Hi David, Perhaps what you describe can explain what I was seeing there: https://lore.kernel.org/v9fs/[email protected]/ Thanks, Pierre On Wed, Apr 15, 2026, at 11:01, David Laight wrote: > On Wed, 15 Apr 2026 07:45:08 +0200 > "Pierre Barre" <[email protected]> wrote: > >> 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 <[email protected]> >> --- >> 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); > > That code isn't really well thought out at all. > The default for buflen seems to be 128k + 24 - 24. > struct p9_rdir adds another 8 bytes, I'm not sure whether that doubles it to > 128k or just adds an extra page (which might be 64k not 4k). > It also looks as though the user can specify an arbitrary buffers size (min 4k). > So who knows how big that (and other associated) buffers actually are. > > The buffer seems to persist across readdir() system calls. > I can't see any code that might attempt to honour seekdir(). > I hope there is a global lock that stops multiple threads issuing readdir() > on the same fd in parallel. > > David > >> 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 >>