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