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