f338ef
From 27f799563c1c2c1986662ed4a3a83d834c04fd98 Mon Sep 17 00:00:00 2001
f338ef
From: Mohit Agrawal <moagrawal@redhat.com>
f338ef
Date: Mon, 14 Oct 2019 15:42:31 +0530
f338ef
Subject: [PATCH 308/308] dht: Rebalance causing IO Error - File descriptor in
f338ef
 bad state
f338ef
f338ef
Problem : When a file is migrated, dht attempts to re-open all open
f338ef
          fds on the new cached subvol. Earlier, if dht had not opened the fd,
f338ef
          the client xlator would be unable to find the remote fd and would
f338ef
          fall back to using an anon fd for the fop. That behavior changed with
f338ef
          https://review.gluster.org/#/c/glusterfs/+/15804, causing fops to fail
f338ef
          with EBADFD if the fd was not available on the cached subvol.
f338ef
          The client xlator returns EBADFD if the remote fd is not found but
f338ef
          dht only checks for EBADF before re-opening fds on the new cached subvol.
f338ef
f338ef
Solution: Handle EBADFD at dht code path to avoid the issue
f338ef
f338ef
> Change-Id: I43c51995cdd48d05b12e4b2889c8dbe2bb2a72d8
f338ef
> Fixes: bz#1758579
f338ef
> Signed-off-by: Mohit Agrawal <moagrawa@redhat.com>
f338ef
> (Cherry pick from commit 9314a9fbf487614c736cf6c4c1b93078d37bb9df)
f338ef
> (Reviewed on upstream link https://review.gluster.org/#/c/glusterfs/+/23518/)
f338ef
f338ef
Change-Id: I43c51995cdd48d05b12e4b2889c8dbe2bb2a72d8
f338ef
BUG: 1758432
f338ef
Signed-off-by: Mohit Agrawal <moagrawa@redhat.com>
f338ef
Reviewed-on: https://code.engineering.redhat.com/gerrit/183370
f338ef
Tested-by: RHGS Build Bot <nigelb@redhat.com>
f338ef
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
f338ef
---
f338ef
 xlators/cluster/dht/src/dht-common.c      | 27 +++++++++++++++++---
f338ef
 xlators/cluster/dht/src/dht-common.h      | 19 ++++++++++++++
f338ef
 xlators/cluster/dht/src/dht-helper.c      | 29 +++++++++++++++++++++
f338ef
 xlators/cluster/dht/src/dht-inode-read.c  | 42 +++++++++++++++++++++++++++----
f338ef
 xlators/cluster/dht/src/dht-inode-write.c | 16 ++++++------
f338ef
 5 files changed, 116 insertions(+), 17 deletions(-)
f338ef
f338ef
diff --git a/xlators/cluster/dht/src/dht-common.c b/xlators/cluster/dht/src/dht-common.c
f338ef
index 99cccd6..37952ba 100644
f338ef
--- a/xlators/cluster/dht/src/dht-common.c
f338ef
+++ b/xlators/cluster/dht/src/dht-common.c
f338ef
@@ -53,6 +53,17 @@ dht_set_dir_xattr_req(xlator_t *this, loc_t *loc, dict_t *xattr_req);
f338ef
 int
f338ef
 dht_do_fresh_lookup(call_frame_t *frame, xlator_t *this, loc_t *loc);
f338ef
 
f338ef
+/* Check the xdata to make sure EBADF has been set by client xlator */
f338ef
+int32_t
f338ef
+dht_check_remote_fd_failed_error(dht_local_t *local, int op_ret, int op_errno)
f338ef
+{
f338ef
+    if (op_ret == -1 && (op_errno == EBADF || op_errno == EBADFD) &&
f338ef
+        !(local->fd_checked)) {
f338ef
+        return 1;
f338ef
+    }
f338ef
+    return 0;
f338ef
+}
f338ef
+
f338ef
 /* Sets the blocks and size values to fixed values. This is to be called
f338ef
  * only for dirs. The caller is responsible for checking the type
f338ef
  */
f338ef
@@ -4529,6 +4540,7 @@ dht_getxattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret,
f338ef
     int this_call_cnt = 0;
f338ef
     dht_local_t *local = NULL;
f338ef
     dht_conf_t *conf = NULL;
f338ef
+    int ret = 0;
f338ef
 
f338ef
     VALIDATE_OR_GOTO(frame, err);
f338ef
     VALIDATE_OR_GOTO(frame->local, err);
f338ef
@@ -4537,6 +4549,13 @@ dht_getxattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret,
f338ef
     conf = this->private;
f338ef
     local = frame->local;
f338ef
 
f338ef
+    if (dht_check_remote_fd_failed_error(local, op_ret, op_errno)) {
f338ef
+        ret = dht_check_and_open_fd_on_subvol(this, frame);
f338ef
+        if (ret)
f338ef
+            goto err;
f338ef
+        return 0;
f338ef
+    }
f338ef
+
f338ef
     LOCK(&frame->lock);
f338ef
     {
f338ef
         if (!xattr || (op_ret == -1)) {
f338ef
@@ -5204,8 +5223,8 @@ dht_file_setxattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
f338ef
 
f338ef
     local->op_errno = op_errno;
f338ef
 
f338ef
-    if ((local->fop == GF_FOP_FSETXATTR) && op_ret == -1 &&
f338ef
-        (op_errno == EBADF) && !(local->fd_checked)) {
f338ef
+    if ((local->fop == GF_FOP_FSETXATTR) &&
f338ef
+        dht_check_remote_fd_failed_error(local, op_ret, op_errno)) {
f338ef
         ret = dht_check_and_open_fd_on_subvol(this, frame);
f338ef
         if (ret)
f338ef
             goto out;
f338ef
@@ -5929,8 +5948,8 @@ dht_file_removexattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
f338ef
 
f338ef
     local->op_errno = op_errno;
f338ef
 
f338ef
-    if ((local->fop == GF_FOP_FREMOVEXATTR) && (op_ret == -1) &&
f338ef
-        (op_errno == EBADF) && !(local->fd_checked)) {
f338ef
+    if ((local->fop == GF_FOP_FREMOVEXATTR) &&
f338ef
+        dht_check_remote_fd_failed_error(local, op_ret, op_errno)) {
f338ef
         ret = dht_check_and_open_fd_on_subvol(this, frame);
f338ef
         if (ret)
f338ef
             goto out;
f338ef
diff --git a/xlators/cluster/dht/src/dht-common.h b/xlators/cluster/dht/src/dht-common.h
f338ef
index c516271..ce11f02 100644
f338ef
--- a/xlators/cluster/dht/src/dht-common.h
f338ef
+++ b/xlators/cluster/dht/src/dht-common.h
f338ef
@@ -1230,6 +1230,22 @@ dht_newfile_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret,
f338ef
                 struct iatt *preparent, struct iatt *postparent, dict_t *xdata);
f338ef
 
f338ef
 int
f338ef
+dht_finodelk_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
f338ef
+                 int32_t op_ret, int32_t op_errno, dict_t *xdata);
f338ef
+
f338ef
+int
f338ef
+dht_getxattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret,
f338ef
+                 int op_errno, dict_t *xattr, dict_t *xdata);
f338ef
+
f338ef
+int
f338ef
+dht_common_xattrop_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
f338ef
+                       int32_t op_ret, int32_t op_errno, dict_t *dict,
f338ef
+                       dict_t *xdata);
f338ef
+int
f338ef
+dht_fxattrop_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
f338ef
+                 int32_t op_ret, int32_t op_errno, dict_t *dict, dict_t *xdata);
f338ef
+
f338ef
+int
f338ef
 gf_defrag_status_get(dht_conf_t *conf, dict_t *dict);
f338ef
 
f338ef
 void
f338ef
@@ -1525,4 +1541,7 @@ int
f338ef
 dht_pt_rename(call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc,
f338ef
               dict_t *xdata);
f338ef
 
f338ef
+int32_t
f338ef
+dht_check_remote_fd_failed_error(dht_local_t *local, int op_ret, int op_errno);
f338ef
+
f338ef
 #endif /* _DHT_H */
f338ef
diff --git a/xlators/cluster/dht/src/dht-helper.c b/xlators/cluster/dht/src/dht-helper.c
f338ef
index 1e9fee0..4f7370d 100644
f338ef
--- a/xlators/cluster/dht/src/dht-helper.c
f338ef
+++ b/xlators/cluster/dht/src/dht-helper.c
f338ef
@@ -366,6 +366,23 @@ dht_check_and_open_fd_on_subvol_complete(int ret, call_frame_t *frame,
f338ef
 
f338ef
             break;
f338ef
 
f338ef
+        case GF_FOP_FXATTROP:
f338ef
+            STACK_WIND(frame, dht_common_xattrop_cbk, subvol,
f338ef
+                       subvol->fops->fxattrop, local->fd,
f338ef
+                       local->rebalance.flags, local->rebalance.xattr,
f338ef
+                       local->xattr_req);
f338ef
+            break;
f338ef
+
f338ef
+        case GF_FOP_FGETXATTR:
f338ef
+            STACK_WIND(frame, dht_getxattr_cbk, subvol, subvol->fops->fgetxattr,
f338ef
+                       local->fd, local->key, NULL);
f338ef
+            break;
f338ef
+
f338ef
+        case GF_FOP_FINODELK:
f338ef
+            STACK_WIND(frame, dht_finodelk_cbk, subvol, subvol->fops->finodelk,
f338ef
+                       local->key, local->fd, local->rebalance.lock_cmd,
f338ef
+                       &local->rebalance.flock, local->xattr_req);
f338ef
+            break;
f338ef
         default:
f338ef
             gf_msg(this->name, GF_LOG_ERROR, 0, DHT_MSG_UNKNOWN_FOP,
f338ef
                    "Unknown FOP on fd (%p) on file %s @ %s", fd,
f338ef
@@ -429,6 +446,18 @@ handle_err:
f338ef
             DHT_STACK_UNWIND(fremovexattr, frame, -1, op_errno, NULL);
f338ef
             break;
f338ef
 
f338ef
+        case GF_FOP_FXATTROP:
f338ef
+            DHT_STACK_UNWIND(fxattrop, frame, -1, op_errno, NULL, NULL);
f338ef
+            break;
f338ef
+
f338ef
+        case GF_FOP_FGETXATTR:
f338ef
+            DHT_STACK_UNWIND(fgetxattr, frame, -1, op_errno, NULL, NULL);
f338ef
+            break;
f338ef
+
f338ef
+        case GF_FOP_FINODELK:
f338ef
+            DHT_STACK_UNWIND(finodelk, frame, -1, op_errno, NULL);
f338ef
+            break;
f338ef
+
f338ef
         default:
f338ef
             gf_msg(this->name, GF_LOG_ERROR, 0, DHT_MSG_UNKNOWN_FOP,
f338ef
                    "Unknown FOP on fd (%p) on file %s @ %s", fd,
f338ef
diff --git a/xlators/cluster/dht/src/dht-inode-read.c b/xlators/cluster/dht/src/dht-inode-read.c
f338ef
index cacfe35..0c209a5 100644
f338ef
--- a/xlators/cluster/dht/src/dht-inode-read.c
f338ef
+++ b/xlators/cluster/dht/src/dht-inode-read.c
f338ef
@@ -162,8 +162,8 @@ dht_file_attr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret,
f338ef
     local = frame->local;
f338ef
     prev = cookie;
f338ef
 
f338ef
-    if ((local->fop == GF_FOP_FSTAT) && (op_ret == -1) && (op_errno == EBADF) &&
f338ef
-        !(local->fd_checked)) {
f338ef
+    if ((local->fop == GF_FOP_FSTAT) &&
f338ef
+        dht_check_remote_fd_failed_error(local, op_ret, op_errno)) {
f338ef
         ret = dht_check_and_open_fd_on_subvol(this, frame);
f338ef
         if (ret)
f338ef
             goto out;
f338ef
@@ -431,7 +431,7 @@ dht_readv_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret,
f338ef
     if (local->call_cnt != 1)
f338ef
         goto out;
f338ef
 
f338ef
-    if (op_ret == -1 && (op_errno == EBADF) && !(local->fd_checked)) {
f338ef
+    if (dht_check_remote_fd_failed_error(local, op_ret, op_errno)) {
f338ef
         ret = dht_check_and_open_fd_on_subvol(this, frame);
f338ef
         if (ret)
f338ef
             goto out;
f338ef
@@ -703,7 +703,7 @@ dht_flush_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret,
f338ef
     if (local->call_cnt != 1)
f338ef
         goto out;
f338ef
 
f338ef
-    if (op_ret == -1 && (op_errno == EBADF) && !(local->fd_checked)) {
f338ef
+    if (dht_check_remote_fd_failed_error(local, op_ret, op_errno)) {
f338ef
         ret = dht_check_and_open_fd_on_subvol(this, frame);
f338ef
         if (ret)
f338ef
             goto out;
f338ef
@@ -820,7 +820,7 @@ dht_fsync_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret,
f338ef
 
f338ef
     local->op_errno = op_errno;
f338ef
 
f338ef
-    if (op_ret == -1 && (op_errno == EBADF) && !(local->fd_checked)) {
f338ef
+    if (dht_check_remote_fd_failed_error(local, op_ret, op_errno)) {
f338ef
         ret = dht_check_and_open_fd_on_subvol(this, frame);
f338ef
         if (ret)
f338ef
             goto out;
f338ef
@@ -1223,6 +1223,13 @@ dht_common_xattrop_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
f338ef
     if (local->call_cnt != 1)
f338ef
         goto out;
f338ef
 
f338ef
+    if (dht_check_remote_fd_failed_error(local, op_ret, op_errno)) {
f338ef
+        ret = dht_check_and_open_fd_on_subvol(this, frame);
f338ef
+        if (ret)
f338ef
+            goto out;
f338ef
+        return 0;
f338ef
+    }
f338ef
+
f338ef
     ret = dht_read_iatt_from_xdata(this, xdata, &stbuf);
f338ef
 
f338ef
     if ((!op_ret) && (ret)) {
f338ef
@@ -1535,8 +1542,26 @@ dht_finodelk_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
f338ef
                  int32_t op_ret, int32_t op_errno, dict_t *xdata)
f338ef
 
f338ef
 {
f338ef
+    dht_local_t *local = NULL;
f338ef
+    int ret = 0;
f338ef
+
f338ef
+    GF_VALIDATE_OR_GOTO("dht", frame, out);
f338ef
+    GF_VALIDATE_OR_GOTO("dht", this, out);
f338ef
+    GF_VALIDATE_OR_GOTO("dht", frame->local, out);
f338ef
+
f338ef
+    local = frame->local;
f338ef
+
f338ef
+    if (dht_check_remote_fd_failed_error(local, op_ret, op_errno)) {
f338ef
+        ret = dht_check_and_open_fd_on_subvol(this, frame);
f338ef
+        if (ret)
f338ef
+            goto out;
f338ef
+        return 0;
f338ef
+    }
f338ef
+
f338ef
+out:
f338ef
     dht_lk_inode_unref(frame, op_ret);
f338ef
     DHT_STACK_UNWIND(finodelk, frame, op_ret, op_errno, xdata);
f338ef
+
f338ef
     return 0;
f338ef
 }
f338ef
 
f338ef
@@ -1574,6 +1599,13 @@ dht_finodelk(call_frame_t *frame, xlator_t *this, const char *volume, fd_t *fd,
f338ef
             if (ret)
f338ef
                     goto err;
f338ef
     */
f338ef
+    local->rebalance.flock = *lock;
f338ef
+    local->rebalance.lock_cmd = cmd;
f338ef
+    local->key = gf_strdup(volume);
f338ef
+
f338ef
+    if (xdata)
f338ef
+        local->xattr_req = dict_ref(xdata);
f338ef
+
f338ef
     STACK_WIND(frame, dht_finodelk_cbk, lock_subvol,
f338ef
                lock_subvol->fops->finodelk, volume, fd, cmd, lock, xdata);
f338ef
 
f338ef
diff --git a/xlators/cluster/dht/src/dht-inode-write.c b/xlators/cluster/dht/src/dht-inode-write.c
f338ef
index b26b705..b6b349d 100644
f338ef
--- a/xlators/cluster/dht/src/dht-inode-write.c
f338ef
+++ b/xlators/cluster/dht/src/dht-inode-write.c
f338ef
@@ -49,7 +49,7 @@ dht_writev_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret,
f338ef
      * We only check once as this could be a valid bad fd error.
f338ef
      */
f338ef
 
f338ef
-    if (op_ret == -1 && (op_errno == EBADF) && !(local->fd_checked)) {
f338ef
+    if (dht_check_remote_fd_failed_error(local, op_ret, op_errno)) {
f338ef
         ret = dht_check_and_open_fd_on_subvol(this, frame);
f338ef
         if (ret)
f338ef
             goto out;
f338ef
@@ -262,8 +262,8 @@ dht_truncate_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret,
f338ef
      * We only check once as this could actually be a valid error.
f338ef
      */
f338ef
 
f338ef
-    if ((local->fop == GF_FOP_FTRUNCATE) && (op_ret == -1) &&
f338ef
-        ((op_errno == EBADF) || (op_errno == EINVAL)) && !(local->fd_checked)) {
f338ef
+    if ((local->fop == GF_FOP_FTRUNCATE) &&
f338ef
+        dht_check_remote_fd_failed_error(local, op_ret, op_errno)) {
f338ef
         ret = dht_check_and_open_fd_on_subvol(this, frame);
f338ef
         if (ret)
f338ef
             goto out;
f338ef
@@ -489,7 +489,7 @@ dht_fallocate_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret,
f338ef
      * We only check once as this could actually be a valid error.
f338ef
      */
f338ef
 
f338ef
-    if ((op_ret == -1) && (op_errno == EBADF) && !(local->fd_checked)) {
f338ef
+    if (dht_check_remote_fd_failed_error(local, op_ret, op_errno)) {
f338ef
         ret = dht_check_and_open_fd_on_subvol(this, frame);
f338ef
         if (ret)
f338ef
             goto out;
f338ef
@@ -666,7 +666,7 @@ dht_discard_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret,
f338ef
      * and a lookup updated the cached subvol in the inode ctx.
f338ef
      * We only check once as this could actually be a valid error.
f338ef
      */
f338ef
-    if ((op_ret == -1) && (op_errno == EBADF) && !(local->fd_checked)) {
f338ef
+    if (dht_check_remote_fd_failed_error(local, op_ret, op_errno)) {
f338ef
         ret = dht_check_and_open_fd_on_subvol(this, frame);
f338ef
         if (ret)
f338ef
             goto out;
f338ef
@@ -838,7 +838,7 @@ dht_zerofill_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret,
f338ef
      * and a lookup updated the cached subvol in the inode ctx.
f338ef
      * We only check once as this could actually be a valid error.
f338ef
      */
f338ef
-    if ((op_ret == -1) && (op_errno == EBADF) && !(local->fd_checked)) {
f338ef
+    if (dht_check_remote_fd_failed_error(local, op_ret, op_errno)) {
f338ef
         ret = dht_check_and_open_fd_on_subvol(this, frame);
f338ef
         if (ret)
f338ef
             goto out;
f338ef
@@ -1005,8 +1005,8 @@ dht_file_setattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
f338ef
 
f338ef
     local->op_errno = op_errno;
f338ef
 
f338ef
-    if ((local->fop == GF_FOP_FSETATTR) && (op_ret == -1) &&
f338ef
-        (op_errno == EBADF) && !(local->fd_checked)) {
f338ef
+    if ((local->fop == GF_FOP_FSETATTR) &&
f338ef
+        dht_check_remote_fd_failed_error(local, op_ret, op_errno)) {
f338ef
         ret = dht_check_and_open_fd_on_subvol(this, frame);
f338ef
         if (ret)
f338ef
             goto out;
f338ef
-- 
f338ef
1.8.3.1
f338ef