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