Blob Blame History Raw
From a68b0bf00a1f646f25cdedecd084e9e02afc5943 Mon Sep 17 00:00:00 2001
From: Poornima G <pgurusid@redhat.com>
Date: Mon, 27 Mar 2017 11:38:28 +0530
Subject: [PATCH 370/375] reddir-ahead: Fix EOD propagation problem

In readdirp fop, op_errno is overloaded to indicate the EOD detection.
If op_errno contains ENOENT, then it indicates that there are no
further entries pending read in the directory. Currently NFS uses the
ENOENT to identify the EOD.

Issue:
NFS clients issues a 4K buffer for readdirp, readdir-ahead converts it
to 128K buffer as its reading ahead. If there are 100 entries in the
bricks, 128K can get all 100 and store in readdir-ahead, but only 23
entries that can be fit in 4K will be sent to NFS. Since the whole
100 entries were read from brick, the op_errno is set to ENOENT, and
the op_errno is propagated as is when sent to NFS. Hence NFS client
in reading 23 entries thinks it reached EOD.

Solution:
Do not propogate ENOENT errno, unless all the entries are read
from the readdir ahead buffer.

> Reviewed-on: https://review.gluster.org/16953
> Smoke: Gluster Build System <jenkins@build.gluster.org>
> Reviewed-by: Raghavendra G <rgowdapp@redhat.com>
> NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org>
> CentOS-regression: Gluster Build System <jenkins@build.gluster.org>
> Signed-off-by: Poornima G <pgurusid@redhat.com>

Change-Id: I4f173a77b21ab9e98ae35e291a45b8fc0cde65bd
BUG: 1427096
Signed-off-by: Poornima G <pgurusid@redhat.com>
Reviewed-on: https://code.engineering.redhat.com/gerrit/102516
Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
---
 xlators/performance/readdir-ahead/src/readdir-ahead.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/xlators/performance/readdir-ahead/src/readdir-ahead.c b/xlators/performance/readdir-ahead/src/readdir-ahead.c
index 13e3a43..f95be50 100644
--- a/xlators/performance/readdir-ahead/src/readdir-ahead.c
+++ b/xlators/performance/readdir-ahead/src/readdir-ahead.c
@@ -236,6 +236,10 @@ rda_readdirp(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size,
                 ret = __rda_serve_readdirp (this, ctx, size, &entries,
                                             &op_errno);
                 serve = _gf_true;
+
+                if (op_errno == ENOENT && !((ctx->state & RDA_FD_EOD) &&
+                                            (ctx->cur_size == 0)))
+                        op_errno = 0;
         } else {
                 ctx->stub = fop_readdirp_stub (frame, NULL, fd, size, off,
                                                xdata);
@@ -380,6 +384,10 @@ out:
 		ctx->fill_frame = NULL;
 	}
 
+        if (op_errno == ENOENT && !((ctx->state & RDA_FD_EOD) &&
+                                    (ctx->cur_size == 0)))
+                op_errno = 0;
+
 	UNLOCK(&ctx->lock);
 
         if (serve) {
-- 
1.8.3.1