From 83adb57ec7ca18b9c5d1290e88b1fe139b280f66 Mon Sep 17 00:00:00 2001
From: Wenguang Wang <wenguangw@vmware.com>
Date: Fri, 28 Jul 2017 16:19:44 -0700
Subject: [PATCH] p9fs_dir_readdir offset support

In the linux 9p client fs module, in readdir implementation, we do not check
for current offset position (which could have been changed by a seek call), and
keep returning (now incorrect) data from the already read and remaining buffer.
---
 fs/9p/vfs_dir.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c
index 5cc00e56206e..a876cc9a473a 100644
--- a/fs/9p/vfs_dir.c
+++ b/fs/9p/vfs_dir.c
@@ -45,6 +45,7 @@
  * struct p9_rdir - readdir accounting
  * @head: start offset of current dirread buffer
  * @tail: end offset of current dirread buffer
+ * @pos: expected dir offset to read the dirread buffer @head
  * @buf: dirread buffer
  *
  * private structure for keeping track of readdir
@@ -54,6 +55,7 @@
 struct p9_rdir {
 	int head;
 	int tail;
+	off_t pos;
 	uint8_t buf[];
 };
 
@@ -130,7 +132,7 @@ static int v9fs_dir_readdir(struct file *file, struct dir_context *ctx)
 	kvec.iov_len = buflen;
 
 	while (1) {
-		if (rdir->tail == rdir->head) {
+		if (rdir->tail == rdir->head || rdir->pos != ctx->pos) {
 			struct iov_iter to;
 			int n;
 			iov_iter_kvec(&to, READ | ITER_KVEC, &kvec, 1, buflen);
@@ -162,6 +164,7 @@ static int v9fs_dir_readdir(struct file *file, struct dir_context *ctx)
 				return 0;
 
 			rdir->head += reclen;
+			rdir->pos += reclen;
 			ctx->pos += reclen;
 		}
 	}
@@ -191,7 +194,7 @@ static int v9fs_dir_readdir_dotl(struct file *file, struct dir_context *ctx)
 		return -ENOMEM;
 
 	while (1) {
-		if (rdir->tail == rdir->head) {
+		if (rdir->tail == rdir->head || rdir->pos != ctx->pos) {
 			err = p9_client_readdir(fid, rdir->buf, buflen,
 						ctx->pos);
 			if (err <= 0)
@@ -218,6 +221,7 @@ static int v9fs_dir_readdir_dotl(struct file *file, struct dir_context *ctx)
 				return 0;
 
 			ctx->pos = curdirent.d_off;
+			rdir->pos = curdirent.d_off;
 			rdir->head += err;
 		}
 	}
-- 
2.11.0