e3c68b
From aef8e51b9974603d397cc8f5301b24451d012e46 Mon Sep 17 00:00:00 2001
e3c68b
From: Susant Palai <spalai@redhat.com>
e3c68b
Date: Fri, 24 Apr 2020 13:32:51 +0530
e3c68b
Subject: [PATCH 367/367] dht: Handle setxattr and rm race for directory in
e3c68b
 rebalance
e3c68b
e3c68b
Problem: Selfheal as part of directory does not return an error if
e3c68b
the layout setxattr fails. This is because the actual lookup fop
e3c68b
must have been successful to proceed for layout heal. Hence, we could
e3c68b
not tell if fix-layout failed in rebalance.
e3c68b
e3c68b
Solution: We can check this information in the layout structure that
e3c68b
whether all the xlators have returned error.
e3c68b
e3c68b
> fixes: #1200
e3c68b
> hange-Id: I3e5f2a36c0d934c21476a73a9a5473d8e490cde7
e3c68b
> Signed-off-by: Susant Palai <spalai@redhat.com>
e3c68b
(backport of https://review.gluster.org/#/c/glusterfs/+/24375/)
e3c68b
e3c68b
BUG: 1812789
e3c68b
Change-Id: I897826c4c2e883b3085c9314deff32d649b4588e
e3c68b
Signed-off-by: Susant Palai <spalai@redhat.com>
e3c68b
Reviewed-on: https://code.engineering.redhat.com/gerrit/198726
e3c68b
Reviewed-by: Mohit Agrawal <moagrawa@redhat.com>
e3c68b
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
e3c68b
---
e3c68b
 xlators/cluster/dht/src/dht-common.c    | 19 +++++++++++++++++++
e3c68b
 xlators/cluster/dht/src/dht-common.h    |  3 +++
e3c68b
 xlators/cluster/dht/src/dht-rebalance.c | 11 +++++++++++
e3c68b
 3 files changed, 33 insertions(+)
e3c68b
e3c68b
diff --git a/xlators/cluster/dht/src/dht-common.c b/xlators/cluster/dht/src/dht-common.c
e3c68b
index d0b5287..7890e7a 100644
e3c68b
--- a/xlators/cluster/dht/src/dht-common.c
e3c68b
+++ b/xlators/cluster/dht/src/dht-common.c
e3c68b
@@ -11286,3 +11286,22 @@ dht_pt_fgetxattr(call_frame_t *frame, xlator_t *this, fd_t *fd, const char *key,
e3c68b
                FIRST_CHILD(this)->fops->fgetxattr, fd, key, xdata);
e3c68b
     return 0;
e3c68b
 }
e3c68b
+
e3c68b
+/* The job of this function is to check if all the xlators have updated
e3c68b
+ * error in the layout. */
e3c68b
+int
e3c68b
+dht_dir_layout_error_check(xlator_t *this, inode_t *inode)
e3c68b
+{
e3c68b
+    dht_layout_t *layout = NULL;
e3c68b
+    int i = 0;
e3c68b
+
e3c68b
+    layout = dht_layout_get(this, inode);
e3c68b
+    for (i = 0; i < layout->cnt; i++) {
e3c68b
+        if (layout->list[i].err == 0) {
e3c68b
+            return 0;
e3c68b
+        }
e3c68b
+    }
e3c68b
+
e3c68b
+    /* Returning the first xlator error as all xlators have errors */
e3c68b
+    return layout->list[0].err;
e3c68b
+}
e3c68b
diff --git a/xlators/cluster/dht/src/dht-common.h b/xlators/cluster/dht/src/dht-common.h
e3c68b
index ce11f02..4d2aae6 100644
e3c68b
--- a/xlators/cluster/dht/src/dht-common.h
e3c68b
+++ b/xlators/cluster/dht/src/dht-common.h
e3c68b
@@ -1544,4 +1544,7 @@ dht_pt_rename(call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc,
e3c68b
 int32_t
e3c68b
 dht_check_remote_fd_failed_error(dht_local_t *local, int op_ret, int op_errno);
e3c68b
 
e3c68b
+int
e3c68b
+dht_dir_layout_error_check(xlator_t *this, inode_t *inode);
e3c68b
+
e3c68b
 #endif /* _DHT_H */
e3c68b
diff --git a/xlators/cluster/dht/src/dht-rebalance.c b/xlators/cluster/dht/src/dht-rebalance.c
e3c68b
index 7d9df02..33cacfe 100644
e3c68b
--- a/xlators/cluster/dht/src/dht-rebalance.c
e3c68b
+++ b/xlators/cluster/dht/src/dht-rebalance.c
e3c68b
@@ -3928,6 +3928,17 @@ gf_defrag_fix_layout(xlator_t *this, gf_defrag_info_t *defrag, loc_t *loc,
e3c68b
     }
e3c68b
 
e3c68b
     ret = syncop_setxattr(this, loc, fix_layout, 0, NULL, NULL);
e3c68b
+
e3c68b
+    /* In case of a race where the directory is deleted just before
e3c68b
+     * layout setxattr, the errors are updated in the layout structure.
e3c68b
+     * We can use this information to make a decision whether the directory
e3c68b
+     * is deleted entirely.
e3c68b
+     */
e3c68b
+    if (ret == 0) {
e3c68b
+        ret = dht_dir_layout_error_check(this, loc->inode);
e3c68b
+        ret = -ret;
e3c68b
+    }
e3c68b
+
e3c68b
     if (ret) {
e3c68b
         if (-ret == ENOENT || -ret == ESTALE) {
e3c68b
             gf_msg(this->name, GF_LOG_INFO, -ret, DHT_MSG_LAYOUT_FIX_FAILED,
e3c68b
-- 
e3c68b
1.8.3.1
e3c68b