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