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