Avoid calling the underlying ->readdir() again when we reached the end already; keep going round the loop only if we stopped due to our own buffer being full. Signed-off-by: David Woodhouse <David.Woodhouse@xxxxxxxxx> diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index d789fb8..7631bd1 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -1832,6 +1832,7 @@ struct buffered_dirent { struct readdir_data { char *dirent; size_t used; + int full; }; static int nfsd_buffered_filldir(void *__buf, const char *name, int namlen, @@ -1842,8 +1843,10 @@ static int nfsd_buffered_filldir(void *__buf, const char *name, int namlen, unsigned int reclen; reclen = ALIGN(sizeof(struct buffered_dirent) + namlen, sizeof(u64)); - if (buf->used + reclen > PAGE_SIZE) + if (buf->used + reclen > PAGE_SIZE) { + buf->full = 1; return -EINVAL; + } de->namlen = namlen; de->offset = offset; @@ -1871,11 +1874,11 @@ static int nfsd_buffered_readdir(struct file *file, filldir_t func, offset = *offsetp; cdp->err = nfserr_eof; /* will be cleared on successful read */ - while (1) { + do { unsigned int reclen; buf.used = 0; - + buf.full = 0; host_err = vfs_readdir(file, nfsd_buffered_filldir, &buf); if (host_err) break; @@ -1903,7 +1906,7 @@ static int nfsd_buffered_readdir(struct file *file, filldir_t func, de = (struct buffered_dirent *)((char *)de + reclen); } offset = vfs_llseek(file, 0, 1); - } + } while (buf.full); done: free_page((unsigned long)(buf.dirent)); -- David Woodhouse Open Source Technology Centre David.Woodhouse@xxxxxxxxx Intel Corporation -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html