diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c
index cae53d4..735bb60 100644
--- a/fs/9p/vfs_dir.c
+++ b/fs/9p/vfs_dir.c
@@ -75,6 +75,7 @@ static int v9fs_dir_readdir(struct file *filp, void *dirent,
        int buflen;
        char *statbuf;
        int n, i = 0;
+       int reclen = 0;

        P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name
        fid = filp->private_data;
@@ -85,13 +86,35 @@ static int v9fs_dir_readdir(struct file *filp, void *diren
                return -ENOMEM;

        while (1) {
-               err = v9fs_file_readn(filp, statbuf, NULL, buflen,
+               if (fid->rdir_fpos > filp->f_pos) {
+                       n = fid->rdir_fpos - filp->f_pos;
+                       if (n > buflen) {
+                               printk(KERN_ERR
+                                       "9p: readdir: n=%d buflen=%d\n",
+                                       n, buflen);
+                               err = -EIO;
+                               goto free_and_exit;
+                       }
+                       if (!fid->aux) {
+                               printk(KERN_ERR
+                               "9p: readdir: null aux rd=%d fp=%d\n",
+                                       fid->rdir_fpos, filp->f_pos);
+                               err = -EIO;
+                               goto free_and_exit;
+                       }
+                       memcpy(statbuf, fid->aux, n);
+                       /* TODO: would it make more sense to leave buffer? */
+                       kfree(fid->aux);
+                       fid->aux = NULL;
+               } else {
+                       err = v9fs_file_readn(filp, statbuf, NULL, buflen,
                                                                fid->rdir_fpos
-               if (err <= 0)
-                       break;
-
+                       if (err <= 0)
+                               break;
+                       n = err;
+                       fid->rdir_fpos += n;
+               }
                i = 0;
-               n = err;
                while (i < n) {
                        err = p9stat_read(statbuf + i, buflen-i, &st,
                                                        fid->clnt->dotu);
@@ -101,21 +124,32 @@ static int v9fs_dir_readdir(struct file *filp, void *dir
                                p9stat_free(&st);
                                goto free_and_exit;
                        }
-
-                       i += st.size+2;
-                       fid->rdir_fpos += st.size+2;
+                       reclen = st.size+2;

                        over = filldir(dirent, st.name, strlen(st.name),
                            filp->f_pos, v9fs_qid2ino(&st.qid), dt_type(&st));

-                       filp->f_pos += st.size+2;
-
                        p9stat_free(&st);

                        if (over) {
+                               /* TODO: alloc msize buffer instead? */
+                               if (fid->aux) {
+                                       printk(KERN_ERR "9p: readdir: aux\n");
+                                       err = -EIO;
+                                       goto free_and_exit;
+                               }
+                               fid->aux = kmalloc(n - i, GFP_KERNEL);
+                               if (!fid->aux) {
+                                       err = -ENOMEM;
+                                       goto free_and_exit;
+                               }
+                               memcpy(fid->aux, statbuf + i, n - i);
+
                                err = 0;
                                goto free_and_exit;
                        }
+                       filp->f_pos += reclen;
+                       i += reclen;
                }
        }

diff --git a/net/9p/client.c b/net/9p/client.c
index 5bf5f22..31f01e3 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -609,6 +609,8 @@ static void p9_fid_destroy(struct p9_fid *fid)
        spin_lock_irqsave(&clnt->lock, flags);
        list_del(&fid->flist);
        spin_unlock_irqrestore(&clnt->lock, flags);
+       if (fid->aux)
+               kfree(fid->aux);
        kfree(fid);
 }

