From 929d71b084e1e7f995d3a2884d16438108f6f621 Mon Sep 17 00:00:00 2001
From: Erik Jacobson <erik.jacobson@hpe.com>
Date: Wed, 10 Apr 2024 06:45:02 -0500
Subject: [PATCH] prevent gnfs IO Errors on smaller files (#4322)

In certain situations, smaller files will report I/O errors when accessed
from NFS using Gluster NFS. With our settings, files up to 170M could report
this in some cases. It was not a consistent failure.

Disbling the NFS performance I/O cache seemed to work around the instances
of the problem observed for non-sharded volumes.

Research showed that gluster NFS is relying on an errno return value of
EINVAL to detect EOF and set is_eof. However, in some paths this value
was not retained or was reset to zero.

This change passes the errno along so it can be used by gluster NFS. We
found the issue in the shard xlator and the io-cache xlator.

Signed-off-by: Erik Jacobson <erikj@tdkt.org>
Co-authored-by: Erik Jacobson <erikj@sgi.com>
---
 xlators/features/shard/src/shard.c      | 5 ++++-
 xlators/performance/io-cache/src/page.c | 4 +++-
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/xlators/features/shard/src/shard.c b/xlators/features/shard/src/shard.c
index c902397..684d115 100644
--- a/xlators/features/shard/src/shard.c
+++ b/xlators/features/shard/src/shard.c
@@ -4931,8 +4931,11 @@ shard_readv_do_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
         goto out;
     }
 
-    if (local->op_ret >= 0)
+    if (local->op_ret >= 0) {
         local->op_ret += op_ret;
+        /* gnfs requires op_errno to determine is_eof */
+        local->op_errno = op_errno;
+    }
 
     shard_inode_ctx_get(anon_fd->inode, this, &ctx);
     block_num = ctx->block_num;
diff --git a/xlators/performance/io-cache/src/page.c b/xlators/performance/io-cache/src/page.c
index 1ef25f7..57bd244 100644
--- a/xlators/performance/io-cache/src/page.c
+++ b/xlators/performance/io-cache/src/page.c
@@ -797,9 +797,11 @@ ioc_frame_unwind(call_frame_t *frame)
         goto unwind;
     }
 
+    /* gnfs requires op_errno to determine is_eof */
+    op_errno = local->op_errno;
+
     if (local->op_ret < 0) {
         op_ret = local->op_ret;
-        op_errno = local->op_errno;
         goto unwind;
     }
 
-- 
2.27.0

