21ab4e
From 902a257fad46d58775824b5cf6abd3c3ab1da724 Mon Sep 17 00:00:00 2001
21ab4e
From: Jiffin Tony Thottan <jthottan@redhat.com>
21ab4e
Date: Thu, 18 May 2017 11:22:16 +0530
21ab4e
Subject: [PATCH 527/529] dht/hardlink : Remove stale linkto file incase of
21ab4e
 failure
21ab4e
21ab4e
This is a similar issue fixed for rename in https://review.gluster.org/#/c/16016/
21ab4e
For hardlinks, if cached and hashed subvolumes are different, then it will first
21ab4e
create linkto file in hashed using root permission, but actually hardlink creation
21ab4e
fails with EACESS and stale linkto file is never removed.All the followup hardlink
21ab4e
calls with file name will result ESTALE because linktofile creation fails with EEXIST
21ab4e
and follow up lookup on linkto file returns gfid-mismatching(old linkto file) and
21ab4e
finally fails with ESTALE
21ab4e
21ab4e
Steps to produce :
21ab4e
(From link/00.t test from posix-testsuite)
21ab4e
Steps executed in script
21ab4e
 * create a file "abc" using root
21ab4e
 * change the ownership of file to a non root user
21ab4e
 * create hardlink "link" for "abc" using a non root user, it fails with EACESS
21ab4e
 * delete "abc"
21ab4e
 * create directory "abc" using root
21ab4e
 * again try to create hadrlink "link" for "abc" using non root user, fails with ESTALE
21ab4e
21ab4e
Also tried to fix other bugs in dht_linkfile_create_cbk() and posix_lookup.
21ab4e
21ab4e
Thanks Susant for the help in debugging the issue and suggestion for this patch.
21ab4e
21ab4e
Upstrem reference :
21ab4e
>Change-Id: I7a5a1899d3fd1fdb13578b37f9d52a084492e35d
21ab4e
>BUG: 1452084
21ab4e
>Signed-off-by: Jiffin Tony Thottan <jthottan@redhat.com>
21ab4e
>Reviewed-on: https://review.gluster.org/17331
21ab4e
>Smoke: Gluster Build System <jenkins@build.gluster.org>
21ab4e
>Reviewed-by: N Balachandran <nbalacha@redhat.com>
21ab4e
>CentOS-regression: Gluster Build System <jenkins@build.gluster.org>
21ab4e
>Reviewed-by: Raghavendra G <rgowdapp@redhat.com>
21ab4e
>Signed-off-by: Jiffin Tony Thottan <jthottan@redhat.com>
21ab4e
21ab4e
Change-Id: I7a5a1899d3fd1fdb13578b37f9d52a084492e35d
21ab4e
BUG: 1452083
21ab4e
Signed-off-by: Jiffin Tony Thottan <jthottan@redhat.com>
21ab4e
Reviewed-on: https://code.engineering.redhat.com/gerrit/109763
21ab4e
Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
21ab4e
Reviewed-by: Nithya Balachandran <nbalacha@redhat.com>
21ab4e
---
21ab4e
 xlators/cluster/dht/src/dht-common.c   | 73 ++++++++++++++++++++++++++++++++++
21ab4e
 xlators/cluster/dht/src/dht-common.h   |  6 +++
21ab4e
 xlators/cluster/dht/src/dht-linkfile.c |  3 +-
21ab4e
 xlators/storage/posix/src/posix.c      |  3 ++
21ab4e
 4 files changed, 84 insertions(+), 1 deletion(-)
21ab4e
21ab4e
diff --git a/xlators/cluster/dht/src/dht-common.c b/xlators/cluster/dht/src/dht-common.c
21ab4e
index 7465275..480dcbf 100644
21ab4e
--- a/xlators/cluster/dht/src/dht-common.c
21ab4e
+++ b/xlators/cluster/dht/src/dht-common.c
21ab4e
@@ -6438,10 +6438,32 @@ dht_link_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
21ab4e
         int           ret = -1;
21ab4e
         gf_boolean_t  stbuf_merged = _gf_false;
21ab4e
         xlator_t     *subvol = NULL;
21ab4e
+        call_frame_t *cleanup_frame = NULL;
21ab4e
+        dht_local_t  *cleanup_local = NULL;
21ab4e
 
21ab4e
         local = frame->local;
21ab4e
 
21ab4e
         if (op_ret == -1) {
21ab4e
+                /* Remove the linkto if exists */
21ab4e
+                if (local->linked) {
21ab4e
+                        cleanup_frame = create_frame (this, this->ctx->pool);
21ab4e
+                        if (cleanup_frame) {
21ab4e
+                                cleanup_local = dht_local_init (cleanup_frame,
21ab4e
+                                                                &local->loc2,
21ab4e
+                                                                NULL, 0);
21ab4e
+                                if (!cleanup_local || !local->link_subvol) {
21ab4e
+                                        DHT_STACK_DESTROY (cleanup_frame);
21ab4e
+                                        goto out;
21ab4e
+                                }
21ab4e
+                                cleanup_local->link_subvol = local->link_subvol;
21ab4e
+                                FRAME_SU_DO (cleanup_frame, dht_local_t);
21ab4e
+                                ret = synctask_new (this->ctx->env,
21ab4e
+                                                    dht_remove_stale_linkto,
21ab4e
+                                                    dht_remove_stale_linkto_cbk,
21ab4e
+                                                    cleanup_frame,
21ab4e
+                                                    cleanup_frame);
21ab4e
+                        }
21ab4e
+                }
21ab4e
                 /* No continuation on DHT inode missing errors, as we should
21ab4e
                  * then have a good stbuf that states P2 happened. We would
21ab4e
                  * get inode missing if, the file completed migrated between
21ab4e
@@ -9592,3 +9614,54 @@ dht_release (xlator_t *this, fd_t *fd)
21ab4e
 {
21ab4e
         return dht_fd_ctx_destroy (this, fd);
21ab4e
 }
21ab4e
+
21ab4e
+int
21ab4e
+dht_remove_stale_linkto (void *data)
21ab4e
+{
21ab4e
+        call_frame_t    *frame = NULL;
21ab4e
+        dht_local_t     *local = NULL;
21ab4e
+        xlator_t        *this  = NULL;
21ab4e
+        dict_t          *xdata_in = NULL;
21ab4e
+        int             ret = 0;
21ab4e
+
21ab4e
+        GF_VALIDATE_OR_GOTO ("dht", data, out);
21ab4e
+
21ab4e
+        frame = data;
21ab4e
+        local = frame->local;
21ab4e
+        this = frame->this;
21ab4e
+        GF_VALIDATE_OR_GOTO ("dht", this, out);
21ab4e
+        GF_VALIDATE_OR_GOTO ("dht", local, out);
21ab4e
+        GF_VALIDATE_OR_GOTO ("dht", local->link_subvol, out);
21ab4e
+
21ab4e
+        xdata_in = dict_new ();
21ab4e
+        if (!xdata_in)
21ab4e
+                goto out;
21ab4e
+
21ab4e
+        ret = dht_fill_dict_to_avoid_unlink_of_migrating_file (xdata_in);
21ab4e
+        if (ret) {
21ab4e
+                  gf_msg (this->name, GF_LOG_WARNING, -ret, 0,
21ab4e
+                                "Failed to set keys for stale linkto"
21ab4e
+                                "deletion on path %s", local->loc.path);
21ab4e
+                  goto out;
21ab4e
+        }
21ab4e
+
21ab4e
+        ret = syncop_unlink (local->link_subvol, &local->loc, xdata_in, NULL);
21ab4e
+        if (ret) {
21ab4e
+                  gf_msg (this->name, GF_LOG_WARNING, -ret, 0,
21ab4e
+                                "Removal of linkto failed"
21ab4e
+                                " on path %s at subvol %s",
21ab4e
+                                local->loc.path, local->link_subvol->name);
21ab4e
+
21ab4e
+        }
21ab4e
+out:
21ab4e
+        if (xdata_in)
21ab4e
+                dict_unref (xdata_in);
21ab4e
+        return ret;
21ab4e
+}
21ab4e
+
21ab4e
+int
21ab4e
+dht_remove_stale_linkto_cbk (int ret, call_frame_t *sync_frame, void *data)
21ab4e
+{
21ab4e
+        DHT_STACK_DESTROY (sync_frame);
21ab4e
+        return 0;
21ab4e
+}
21ab4e
diff --git a/xlators/cluster/dht/src/dht-common.h b/xlators/cluster/dht/src/dht-common.h
21ab4e
index 81471f7..b35ef0c 100644
21ab4e
--- a/xlators/cluster/dht/src/dht-common.h
21ab4e
+++ b/xlators/cluster/dht/src/dht-common.h
21ab4e
@@ -1260,4 +1260,10 @@ getChoices (const char *value);
21ab4e
 int
21ab4e
 dht_aggregate_split_brain_xattr (dict_t *dst, char *key, data_t *value);
21ab4e
 
21ab4e
+int
21ab4e
+dht_remove_stale_linkto (void *data);
21ab4e
+
21ab4e
+int
21ab4e
+dht_remove_stale_linkto_cbk (int ret, call_frame_t *sync_frame, void *data);
21ab4e
+
21ab4e
 #endif/* _DHT_H */
21ab4e
diff --git a/xlators/cluster/dht/src/dht-linkfile.c b/xlators/cluster/dht/src/dht-linkfile.c
21ab4e
index 355d830..101d939 100644
21ab4e
--- a/xlators/cluster/dht/src/dht-linkfile.c
21ab4e
+++ b/xlators/cluster/dht/src/dht-linkfile.c
21ab4e
@@ -88,7 +88,7 @@ dht_linkfile_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
21ab4e
                 }
21ab4e
 
21ab4e
                 STACK_WIND_COOKIE (frame, dht_linkfile_lookup_cbk, subvol,
21ab4e
-                                   subvol, subvol->fops->lookup, &local->loc,
21ab4e
+                                   subvol, subvol->fops->lookup, &local->linkfile.loc,
21ab4e
                                    xattrs);
21ab4e
                 if (xattrs)
21ab4e
                         dict_unref (xattrs);
21ab4e
@@ -119,6 +119,7 @@ dht_linkfile_create (call_frame_t *frame, fop_mknod_cbk_t linkfile_cbk,
21ab4e
         local = frame->local;
21ab4e
         local->linkfile.linkfile_cbk = linkfile_cbk;
21ab4e
         local->linkfile.srcvol = tovol;
21ab4e
+        loc_copy (&local->linkfile.loc, loc);
21ab4e
 
21ab4e
         local->linked = _gf_false;
21ab4e
 
21ab4e
diff --git a/xlators/storage/posix/src/posix.c b/xlators/storage/posix/src/posix.c
21ab4e
index 0524d50..a08d858 100644
21ab4e
--- a/xlators/storage/posix/src/posix.c
21ab4e
+++ b/xlators/storage/posix/src/posix.c
21ab4e
@@ -268,6 +268,9 @@ out:
21ab4e
                 op_ret = -1;
21ab4e
                 op_errno = ENODATA;
21ab4e
         }
21ab4e
+
21ab4e
+        if (op_ret == 0)
21ab4e
+                op_errno = 0;
21ab4e
         STACK_UNWIND_STRICT (lookup, frame, op_ret, op_errno,
21ab4e
                              (loc)?loc->inode:NULL, &buf, xattr, &postparent);
21ab4e
 
21ab4e
-- 
21ab4e
1.8.3.1
21ab4e