cb8e9e
From ae6d9662536d2c6fdb0a26491d1aca50dfd358ef Mon Sep 17 00:00:00 2001
cb8e9e
From: Nithya Balachandran <nbalacha@redhat.com>
cb8e9e
Date: Fri, 5 Jun 2015 14:39:29 +0530
cb8e9e
Subject: [PATCH 11/18] cluster/dht: Fix dht_setxattr to follow files under
cb8e9e
 migration
cb8e9e
cb8e9e
If a file is under migration, any xattrs created on it
cb8e9e
are lost post migration of the file. This is because
cb8e9e
the xattrs are set only on the cached subvol of the source
cb8e9e
and as the source is under migration, it becomes a linkto file
cb8e9e
post migration.
cb8e9e
cb8e9e
Change-Id: Ib8e233b519cf954e7723c6e26b38fa8f9b8c85c0
cb8e9e
BUG: 1047481
cb8e9e
Signed-off-by: Nithya Balachandran <nbalacha@redhat.com>
cb8e9e
Reviewed-on: http://review.gluster.org/10212
cb8e9e
Reviewed-by: Raghavendra G <rgowdapp@redhat.com>
cb8e9e
Tested-by: Raghavendra G <rgowdapp@redhat.com>
cb8e9e
Reviewed-on: https://code.engineering.redhat.com/gerrit/50101
cb8e9e
Reviewed-by: Raghavendra Gowdappa <rgowdapp@redhat.com>
cb8e9e
Tested-by: Raghavendra Gowdappa <rgowdapp@redhat.com>
cb8e9e
---
cb8e9e
 libglusterfs/src/glusterfs.h         |   5 +-
cb8e9e
 tests/bugs/distribute/bug-1193636.c  |  70 +++++++
cb8e9e
 tests/bugs/distribute/bug-1193636.t  |  72 +++++++
cb8e9e
 xlators/cluster/dht/src/dht-common.c | 391 +++++++++++++++++++++++++++++++++--
cb8e9e
 xlators/cluster/ec/src/ec-combine.c  |   1 +
cb8e9e
 xlators/storage/posix/src/posix.c    | 123 +++++++++--
cb8e9e
 6 files changed, 631 insertions(+), 31 deletions(-)
cb8e9e
 create mode 100644 tests/bugs/distribute/bug-1193636.c
cb8e9e
 create mode 100644 tests/bugs/distribute/bug-1193636.t
cb8e9e
cb8e9e
diff --git a/libglusterfs/src/glusterfs.h b/libglusterfs/src/glusterfs.h
cb8e9e
index 9ed02e5..6f20185 100644
cb8e9e
--- a/libglusterfs/src/glusterfs.h
cb8e9e
+++ b/libglusterfs/src/glusterfs.h
cb8e9e
@@ -230,8 +230,9 @@
cb8e9e
 #define DHT_LINKFILE_STR "linkto"
cb8e9e
 #define DHT_COMMITHASH_STR "commithash"
cb8e9e
 
cb8e9e
-#define DHT_SKIP_NON_LINKTO_UNLINK "unlink-only-if-dht-linkto-file"
cb8e9e
-#define DHT_SKIP_OPEN_FD_UNLINK "dont-unlink-for-open-fd"
cb8e9e
+#define DHT_SKIP_NON_LINKTO_UNLINK  "unlink-only-if-dht-linkto-file"
cb8e9e
+#define DHT_SKIP_OPEN_FD_UNLINK     "dont-unlink-for-open-fd"
cb8e9e
+#define DHT_IATT_IN_XDATA_KEY       "dht-get-iatt-in-xattr"
cb8e9e
 
cb8e9e
 /*CTR requires inode dentry link count from posix*/
cb8e9e
 #define CTR_RESPONSE_LINK_COUNT_XDATA "ctr_response_link_count"
cb8e9e
diff --git a/tests/bugs/distribute/bug-1193636.c b/tests/bugs/distribute/bug-1193636.c
cb8e9e
new file mode 100644
cb8e9e
index 0000000..eae9078
cb8e9e
--- /dev/null
cb8e9e
+++ b/tests/bugs/distribute/bug-1193636.c
cb8e9e
@@ -0,0 +1,70 @@
cb8e9e
+#include <stdio.h>
cb8e9e
+#include <stdlib.h>
cb8e9e
+#include <sys/types.h>
cb8e9e
+#include <attr/xattr.h>
cb8e9e
+#include <fcntl.h>
cb8e9e
+#include <string.h>
cb8e9e
+
cb8e9e
+
cb8e9e
+#define MY_XATTR_NAME   "user.ftest"
cb8e9e
+#define MY_XATTR_VAL    "ftestval"
cb8e9e
+
cb8e9e
+
cb8e9e
+void usage (void)
cb8e9e
+{
cb8e9e
+        printf ("Usage : bug-1193636 <filename> <xattr_name> <op>\n");
cb8e9e
+        printf ("   op : 0 - set, 1 - remove\n");
cb8e9e
+}
cb8e9e
+
cb8e9e
+
cb8e9e
+int main (int argc, char **argv)
cb8e9e
+{
cb8e9e
+        int fd;
cb8e9e
+        int err = 0;
cb8e9e
+        char *xattr_name = NULL;
cb8e9e
+        int op = 0;
cb8e9e
+
cb8e9e
+        if (argc != 4) {
cb8e9e
+                usage ();
cb8e9e
+                exit (1);
cb8e9e
+        }
cb8e9e
+
cb8e9e
+        op = atoi (argv[3]);
cb8e9e
+
cb8e9e
+        if ((op != 0) && (op != 1)) {
cb8e9e
+                printf ("Invalid operation specified.\n");
cb8e9e
+                usage ();
cb8e9e
+                exit (1);
cb8e9e
+        }
cb8e9e
+
cb8e9e
+        xattr_name = argv[2];
cb8e9e
+
cb8e9e
+        fd = open(argv[1], O_RDWR);
cb8e9e
+        if (fd == -1) {
cb8e9e
+                printf ("Failed to open file %s\n", argv[1]);
cb8e9e
+                exit (1);
cb8e9e
+        }
cb8e9e
+
cb8e9e
+        if (!op) {
cb8e9e
+                err = fsetxattr (fd, xattr_name, MY_XATTR_VAL,
cb8e9e
+                                 strlen (MY_XATTR_VAL) + 1, XATTR_CREATE);
cb8e9e
+
cb8e9e
+                if (err) {
cb8e9e
+                        printf ("Failed to set xattr %s: %m\n", xattr_name);
cb8e9e
+                        exit (1);
cb8e9e
+                }
cb8e9e
+
cb8e9e
+        } else {
cb8e9e
+                err = fremovexattr (fd, xattr_name);
cb8e9e
+
cb8e9e
+                if (err) {
cb8e9e
+                        printf ("Failed to remove xattr %s: %m\n", xattr_name);
cb8e9e
+                        exit (1);
cb8e9e
+                }
cb8e9e
+        }
cb8e9e
+
cb8e9e
+        close (fd);
cb8e9e
+
cb8e9e
+        return 0;
cb8e9e
+}
cb8e9e
+
cb8e9e
diff --git a/tests/bugs/distribute/bug-1193636.t b/tests/bugs/distribute/bug-1193636.t
cb8e9e
new file mode 100644
cb8e9e
index 0000000..ccde02e
cb8e9e
--- /dev/null
cb8e9e
+++ b/tests/bugs/distribute/bug-1193636.t
cb8e9e
@@ -0,0 +1,72 @@
cb8e9e
+#!/bin/bash
cb8e9e
+
cb8e9e
+. $(dirname $0)/../../include.rc
cb8e9e
+. $(dirname $0)/../../volume.rc
cb8e9e
+
cb8e9e
+
cb8e9e
+checksticky () {
cb8e9e
+        i=0;
cb8e9e
+        while [ ! -k $1 ]; do
cb8e9e
+                sleep 1
cb8e9e
+                i=$((i+1));
cb8e9e
+                if [[ $i == 10 ]]; then
cb8e9e
+                        return $i
cb8e9e
+                fi
cb8e9e
+                echo "Waiting... $i"
cb8e9e
+        done
cb8e9e
+        echo "done ...got out @ $i"
cb8e9e
+        return 0
cb8e9e
+}
cb8e9e
+
cb8e9e
+cleanup;
cb8e9e
+
cb8e9e
+#Basic checks
cb8e9e
+TEST glusterd
cb8e9e
+TEST pidof glusterd
cb8e9e
+TEST $CLI volume info
cb8e9e
+
cb8e9e
+#Create a distributed volume
cb8e9e
+TEST $CLI volume create $V0 $H0:$B0/${V0}{1..3};
cb8e9e
+TEST $CLI volume start $V0
cb8e9e
+
cb8e9e
+# Mount FUSE
cb8e9e
+TEST glusterfs -s $H0 --volfile-id $V0 $M0
cb8e9e
+
cb8e9e
+TEST mkdir $M0/dir1
cb8e9e
+
cb8e9e
+# Create a large file (1GB), so that rebalance takes time
cb8e9e
+dd if=/dev/zero of=$M0/dir1/FILE2 bs=64k count=10240
cb8e9e
+
cb8e9e
+# Rename the file to create a linkto, for rebalance to
cb8e9e
+# act on the file
cb8e9e
+TEST mv $M0/dir1/FILE2 $M0/dir1/FILE1
cb8e9e
+
cb8e9e
+build_tester $(dirname $0)/bug-1193636.c
cb8e9e
+
cb8e9e
+TEST $CLI volume rebalance $V0 start force
cb8e9e
+
cb8e9e
+TEST checksticky $B0/${V0}3/dir1/FILE1
cb8e9e
+
cb8e9e
+TEST setfattr -n "user.test1" -v "test1" $M0/dir1/FILE1
cb8e9e
+TEST setfattr -n "user.test2" -v "test1" $M0/dir1/FILE1
cb8e9e
+TEST setfattr -n "user.test3" -v "test1" $M0/dir1/FILE1
cb8e9e
+
cb8e9e
+TEST $(dirname $0)/bug-1193636 $M0/dir1/FILE1 user.fsetx 0
cb8e9e
+TEST $(dirname $0)/bug-1193636 $M0/dir1/FILE1 user.fremx 0
cb8e9e
+
cb8e9e
+TEST getfattr -n "user.fremx" $M0/dir1/FILE1
cb8e9e
+TEST setfattr -x "user.test2" $M0/dir1/FILE1
cb8e9e
+
cb8e9e
+
cb8e9e
+TEST $(dirname $0)/bug-1193636 $M0/dir1/FILE1 user.fremx 1
cb8e9e
+
cb8e9e
+EXPECT_WITHIN $REBALANCE_TIMEOUT "completed" rebalance_status_field $V0
cb8e9e
+
cb8e9e
+TEST getfattr -n "user.fsetx" $M0/dir1/FILE1
cb8e9e
+TEST getfattr -n "user.test1" $M0/dir1/FILE1
cb8e9e
+TEST ! getfattr -n "user.test2" $M0/dir1/FILE1
cb8e9e
+TEST ! getfattr -n "user.fremx" $M0/dir1/FILE1
cb8e9e
+TEST getfattr -n "user.test3" $M0/dir1/FILE1
cb8e9e
+
cb8e9e
+
cb8e9e
+cleanup;
cb8e9e
diff --git a/xlators/cluster/dht/src/dht-common.c b/xlators/cluster/dht/src/dht-common.c
cb8e9e
index e2749c9..8e78746 100644
cb8e9e
--- a/xlators/cluster/dht/src/dht-common.c
cb8e9e
+++ b/xlators/cluster/dht/src/dht-common.c
cb8e9e
@@ -32,6 +32,13 @@
cb8e9e
 int dht_link2 (xlator_t *this, call_frame_t *frame, int op_ret);
cb8e9e
 
cb8e9e
 int
cb8e9e
+dht_removexattr2 (xlator_t *this, call_frame_t *frame, int op_ret);
cb8e9e
+
cb8e9e
+int
cb8e9e
+dht_setxattr2 (xlator_t *this, call_frame_t *frame, int op_ret);
cb8e9e
+
cb8e9e
+
cb8e9e
+int
cb8e9e
 dht_aggregate_quota_xattr (dict_t *dst, char *key, data_t *value)
cb8e9e
 {
cb8e9e
         int              ret            = -1;
cb8e9e
@@ -96,6 +103,8 @@ out:
cb8e9e
         return ret;
cb8e9e
 }
cb8e9e
 
cb8e9e
+
cb8e9e
+
cb8e9e
 int
cb8e9e
 dht_aggregate (dict_t *this, char *key, data_t *value, void *data)
cb8e9e
 {
cb8e9e
@@ -3265,6 +3274,78 @@ err:
cb8e9e
 }
cb8e9e
 
cb8e9e
 int
cb8e9e
+dht_file_setxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
cb8e9e
+                     int op_ret, int op_errno, dict_t *xdata)
cb8e9e
+{
cb8e9e
+        int           ret  = -1;
cb8e9e
+        dht_local_t  *local = NULL;
cb8e9e
+        call_frame_t *prev = NULL;
cb8e9e
+        struct iatt  *stbuf = NULL;
cb8e9e
+        inode_t      *inode = NULL;
cb8e9e
+        xlator_t     *subvol = NULL;
cb8e9e
+
cb8e9e
+
cb8e9e
+        local = frame->local;
cb8e9e
+        prev = cookie;
cb8e9e
+
cb8e9e
+        local->op_errno = op_errno;
cb8e9e
+
cb8e9e
+        if ((op_ret == -1) && !dht_inode_missing (op_errno)) {
cb8e9e
+                gf_msg_debug (this->name, op_errno,
cb8e9e
+                              "subvolume %s returned -1.",
cb8e9e
+                              prev->this->name);
cb8e9e
+                goto out;
cb8e9e
+        }
cb8e9e
+
cb8e9e
+        if (local->call_cnt != 1)
cb8e9e
+                goto out;
cb8e9e
+
cb8e9e
+        ret = dict_get_bin (xdata, DHT_IATT_IN_XDATA_KEY, (void **) &stbuf);
cb8e9e
+
cb8e9e
+        if ((!op_ret) && !stbuf) {
cb8e9e
+                goto out;
cb8e9e
+        }
cb8e9e
+
cb8e9e
+        local->op_ret = 0;
cb8e9e
+
cb8e9e
+        local->rebalance.target_op_fn = dht_setxattr2;
cb8e9e
+
cb8e9e
+        /* Phase 2 of migration */
cb8e9e
+        if ((op_ret == -1) || IS_DHT_MIGRATION_PHASE2 (stbuf)) {
cb8e9e
+                ret = dht_rebalance_complete_check (this, frame);
cb8e9e
+                if (!ret)
cb8e9e
+                        return 0;
cb8e9e
+        }
cb8e9e
+
cb8e9e
+        /* Phase 1 of migration */
cb8e9e
+        if (IS_DHT_MIGRATION_PHASE1 (stbuf)) {
cb8e9e
+                inode = (local->fd) ? local->fd->inode : local->loc.inode;
cb8e9e
+                dht_inode_ctx_get1 (this, inode, &subvol);
cb8e9e
+                if (subvol) {
cb8e9e
+                        dht_setxattr2 (this, frame, 0);
cb8e9e
+                        return 0;
cb8e9e
+                }
cb8e9e
+                ret = dht_rebalance_in_progress_check (this, frame);
cb8e9e
+                if (!ret)
cb8e9e
+                        return 0;
cb8e9e
+        }
cb8e9e
+
cb8e9e
+out:
cb8e9e
+        if (local->rebalance.xdata)
cb8e9e
+                dict_unref (local->rebalance.xdata);
cb8e9e
+
cb8e9e
+        if (local->fop == GF_FOP_SETXATTR) {
cb8e9e
+                DHT_STACK_UNWIND (setxattr, frame, op_ret, op_errno, NULL);
cb8e9e
+        } else {
cb8e9e
+                DHT_STACK_UNWIND (fsetxattr, frame, op_ret, op_errno, NULL);
cb8e9e
+        }
cb8e9e
+
cb8e9e
+        return 0;
cb8e9e
+}
cb8e9e
+
cb8e9e
+
cb8e9e
+
cb8e9e
+int
cb8e9e
 dht_fsetxattr (call_frame_t *frame, xlator_t *this,
cb8e9e
                fd_t *fd, dict_t *xattr, int flags, dict_t *xdata)
cb8e9e
 {
cb8e9e
@@ -3272,6 +3353,10 @@ dht_fsetxattr (call_frame_t *frame, xlator_t *this,
cb8e9e
         dht_local_t  *local    = NULL;
cb8e9e
         int           op_errno = EINVAL;
cb8e9e
         dht_conf_t   *conf     = NULL;
cb8e9e
+        dht_layout_t *layout   = NULL;
cb8e9e
+        int           ret      = -1;
cb8e9e
+        int           call_cnt = 0;
cb8e9e
+        int           i        = 0;
cb8e9e
 
cb8e9e
         VALIDATE_OR_GOTO (frame, err);
cb8e9e
         VALIDATE_OR_GOTO (this, err);
cb8e9e
@@ -3299,11 +3384,47 @@ dht_fsetxattr (call_frame_t *frame, xlator_t *this,
cb8e9e
                 goto err;
cb8e9e
         }
cb8e9e
 
cb8e9e
-        local->call_cnt = 1;
cb8e9e
+        layout = local->layout;
cb8e9e
+        if (!layout) {
cb8e9e
+                gf_msg_debug (this->name, 0,
cb8e9e
+                              "no layout for fd=%p", fd);
cb8e9e
+                op_errno = EINVAL;
cb8e9e
+                goto err;
cb8e9e
+        }
cb8e9e
+
cb8e9e
+        local->call_cnt = call_cnt = layout->cnt;
cb8e9e
+
cb8e9e
+        if (IA_ISDIR (fd->inode->ia_type)) {
cb8e9e
+                for (i = 0; i < call_cnt; i++) {
cb8e9e
+                        STACK_WIND (frame, dht_err_cbk,
cb8e9e
+                                    layout->list[i].xlator,
cb8e9e
+                                    layout->list[i].xlator->fops->fsetxattr,
cb8e9e
+                                    fd, xattr, flags, NULL);
cb8e9e
+                }
cb8e9e
+
cb8e9e
+        } else {
cb8e9e
+
cb8e9e
+                local->call_cnt = 1;
cb8e9e
+                local->rebalance.xdata = dict_ref (xattr);
cb8e9e
+                local->rebalance.flags = flags;
cb8e9e
+
cb8e9e
+                xdata = xdata ? dict_ref (xdata) : dict_new ();
cb8e9e
+                if (xdata)
cb8e9e
+                        ret = dict_set_dynstr_with_alloc (xdata,
cb8e9e
+                                        DHT_IATT_IN_XDATA_KEY, "yes");
cb8e9e
+                if (ret) {
cb8e9e
+                        gf_msg_debug (this->name, 0,
cb8e9e
+                              "Failed to set dictionary key %s for fd=%p",
cb8e9e
+                               DHT_IATT_IN_XDATA_KEY, fd);
cb8e9e
+                }
cb8e9e
 
cb8e9e
-        STACK_WIND (frame, dht_err_cbk, subvol, subvol->fops->fsetxattr,
cb8e9e
-                    fd, xattr, flags, NULL);
cb8e9e
+                STACK_WIND (frame, dht_file_setxattr_cbk, subvol,
cb8e9e
+                    subvol->fops->fsetxattr, fd, xattr, flags, xdata);
cb8e9e
+
cb8e9e
+                if (xdata)
cb8e9e
+                        dict_unref (xdata);
cb8e9e
 
cb8e9e
+        }
cb8e9e
         return 0;
cb8e9e
 
cb8e9e
 err:
cb8e9e
@@ -3324,6 +3445,7 @@ dht_common_setxattr_cbk (call_frame_t *frame, void *cookie,
cb8e9e
         return 0;
cb8e9e
 }
cb8e9e
 
cb8e9e
+
cb8e9e
 int
cb8e9e
 dht_checking_pathinfo_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
cb8e9e
                            int op_ret, int op_errno, dict_t *xattr,
cb8e9e
@@ -3365,6 +3487,55 @@ out:
cb8e9e
 
cb8e9e
 }
cb8e9e
 
cb8e9e
+
cb8e9e
+int
cb8e9e
+dht_setxattr2 (xlator_t *this, call_frame_t *frame, int op_ret)
cb8e9e
+{
cb8e9e
+        dht_local_t  *local  = NULL;
cb8e9e
+        xlator_t     *subvol = NULL;
cb8e9e
+        int          op_errno = EINVAL;
cb8e9e
+        inode_t      *inode = NULL;
cb8e9e
+
cb8e9e
+        local = frame->local;
cb8e9e
+
cb8e9e
+        inode = (local->fd) ? local->fd->inode : local->loc.inode;
cb8e9e
+
cb8e9e
+        dht_inode_ctx_get1 (this, inode, &subvol);
cb8e9e
+
cb8e9e
+        /* In phase2, dht_migration_complete_check_task will
cb8e9e
+         * reset inode_ctx_reset1 and update local->cached_subvol
cb8e9e
+         * with the dst subvol.
cb8e9e
+         */
cb8e9e
+        if (!subvol)
cb8e9e
+                subvol = local->cached_subvol;
cb8e9e
+
cb8e9e
+        if (!subvol) {
cb8e9e
+                op_errno = EINVAL;
cb8e9e
+                goto err;
cb8e9e
+        }
cb8e9e
+
cb8e9e
+        local->call_cnt = 2; /* This is the second attempt */
cb8e9e
+
cb8e9e
+        if (local->fop == GF_FOP_SETXATTR) {
cb8e9e
+                STACK_WIND (frame, dht_file_setxattr_cbk, subvol,
cb8e9e
+                            subvol->fops->setxattr, &local->loc,
cb8e9e
+                            local->rebalance.xdata, local->rebalance.flags,
cb8e9e
+                            NULL);
cb8e9e
+        } else {
cb8e9e
+                STACK_WIND (frame, dht_file_setxattr_cbk, subvol,
cb8e9e
+                            subvol->fops->fsetxattr, local->fd,
cb8e9e
+                            local->rebalance.xdata, local->rebalance.flags,
cb8e9e
+                            NULL);
cb8e9e
+        }
cb8e9e
+
cb8e9e
+        return 0;
cb8e9e
+
cb8e9e
+err:
cb8e9e
+        DHT_STACK_UNWIND (setxattr, frame, local->op_ret, op_errno, NULL);
cb8e9e
+        return 0;
cb8e9e
+}
cb8e9e
+
cb8e9e
+
cb8e9e
 int
cb8e9e
 dht_setxattr (call_frame_t *frame, xlator_t *this,
cb8e9e
               loc_t *loc, dict_t *xattr, int flags, dict_t *xdata)
cb8e9e
@@ -3588,11 +3759,32 @@ dht_setxattr (call_frame_t *frame, xlator_t *this,
cb8e9e
                 goto err;
cb8e9e
         }
cb8e9e
 
cb8e9e
-        for (i = 0; i < call_cnt; i++) {
cb8e9e
-                STACK_WIND (frame, dht_err_cbk,
cb8e9e
-                            layout->list[i].xlator,
cb8e9e
-                            layout->list[i].xlator->fops->setxattr,
cb8e9e
+        if (IA_ISDIR (loc->inode->ia_type)) {
cb8e9e
+
cb8e9e
+                for (i = 0; i < call_cnt; i++) {
cb8e9e
+                        STACK_WIND (frame, dht_err_cbk,
cb8e9e
+                                    layout->list[i].xlator,
cb8e9e
+                                    layout->list[i].xlator->fops->setxattr,
cb8e9e
+                                    loc, xattr, flags, xdata);
cb8e9e
+                }
cb8e9e
+
cb8e9e
+        } else {
cb8e9e
+
cb8e9e
+                local->rebalance.xdata = dict_ref (xattr);
cb8e9e
+                local->rebalance.flags = flags;
cb8e9e
+                local->call_cnt = 1;
cb8e9e
+
cb8e9e
+                xdata = xdata ? dict_ref (xdata) : dict_new ();
cb8e9e
+                if (xdata)
cb8e9e
+                        ret = dict_set_dynstr_with_alloc (xdata,
cb8e9e
+                                              DHT_IATT_IN_XDATA_KEY, "yes");
cb8e9e
+
cb8e9e
+                STACK_WIND (frame, dht_file_setxattr_cbk,
cb8e9e
+                            subvol, subvol->fops->setxattr,
cb8e9e
                             loc, xattr, flags, xdata);
cb8e9e
+
cb8e9e
+                if (xdata)
cb8e9e
+                        dict_unref (xdata);
cb8e9e
         }
cb8e9e
 
cb8e9e
         return 0;
cb8e9e
@@ -3605,6 +3797,123 @@ err:
cb8e9e
 }
cb8e9e
 
cb8e9e
 
cb8e9e
+
cb8e9e
+
cb8e9e
+int
cb8e9e
+dht_file_removexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
cb8e9e
+                     int op_ret, int op_errno, dict_t *xdata)
cb8e9e
+{
cb8e9e
+        int           ret  = -1;
cb8e9e
+        dht_local_t  *local = NULL;
cb8e9e
+        call_frame_t *prev = NULL;
cb8e9e
+        struct iatt  *stbuf = NULL;
cb8e9e
+        inode_t      *inode = NULL;
cb8e9e
+        xlator_t     *subvol = NULL;
cb8e9e
+
cb8e9e
+
cb8e9e
+        local = frame->local;
cb8e9e
+        prev = cookie;
cb8e9e
+
cb8e9e
+        local->op_errno = op_errno;
cb8e9e
+
cb8e9e
+        if ((op_ret == -1) && !dht_inode_missing (op_errno)) {
cb8e9e
+                gf_msg_debug (this->name, op_errno,
cb8e9e
+                              "subvolume %s returned -1",
cb8e9e
+                              prev->this->name);
cb8e9e
+                goto out;
cb8e9e
+        }
cb8e9e
+
cb8e9e
+        if (local->call_cnt != 1)
cb8e9e
+                goto out;
cb8e9e
+
cb8e9e
+        ret = dict_get_bin (xdata, DHT_IATT_IN_XDATA_KEY, (void **) &stbuf);
cb8e9e
+
cb8e9e
+        if ((!op_ret) && !stbuf) {
cb8e9e
+                goto out;
cb8e9e
+        }
cb8e9e
+
cb8e9e
+        local->op_ret = 0;
cb8e9e
+
cb8e9e
+        local->rebalance.target_op_fn = dht_removexattr2;
cb8e9e
+
cb8e9e
+        /* Phase 2 of migration */
cb8e9e
+        if ((op_ret == -1) || IS_DHT_MIGRATION_PHASE2 (stbuf)) {
cb8e9e
+                ret = dht_rebalance_complete_check (this, frame);
cb8e9e
+                if (!ret)
cb8e9e
+                        return 0;
cb8e9e
+        }
cb8e9e
+
cb8e9e
+        /* Phase 1 of migration */
cb8e9e
+        if (IS_DHT_MIGRATION_PHASE1 (stbuf)) {
cb8e9e
+                inode = (local->fd) ? local->fd->inode : local->loc.inode;
cb8e9e
+                dht_inode_ctx_get1 (this, inode, &subvol);
cb8e9e
+                if (subvol) {
cb8e9e
+                        dht_removexattr2 (this, frame, 0);
cb8e9e
+                        return 0;
cb8e9e
+                }
cb8e9e
+                ret = dht_rebalance_in_progress_check (this, frame);
cb8e9e
+                if (!ret)
cb8e9e
+                        return 0;
cb8e9e
+        }
cb8e9e
+
cb8e9e
+out:
cb8e9e
+        if (local->fop == GF_FOP_REMOVEXATTR) {
cb8e9e
+                DHT_STACK_UNWIND (removexattr, frame, op_ret, op_errno, NULL);
cb8e9e
+        } else {
cb8e9e
+                DHT_STACK_UNWIND (fremovexattr, frame, op_ret, op_errno, NULL);
cb8e9e
+        }
cb8e9e
+        return 0;
cb8e9e
+
cb8e9e
+}
cb8e9e
+
cb8e9e
+int
cb8e9e
+dht_removexattr2 (xlator_t *this, call_frame_t *frame, int op_ret)
cb8e9e
+{
cb8e9e
+        dht_local_t  *local  = NULL;
cb8e9e
+        xlator_t     *subvol = NULL;
cb8e9e
+        int          op_errno = EINVAL;
cb8e9e
+        inode_t      *inode = NULL;
cb8e9e
+
cb8e9e
+        local = frame->local;
cb8e9e
+
cb8e9e
+        inode = (local->fd) ? local->fd->inode : local->loc.inode;
cb8e9e
+
cb8e9e
+        dht_inode_ctx_get1 (this, inode, &subvol);
cb8e9e
+
cb8e9e
+        /* In phase2, dht_migration_complete_check_task will
cb8e9e
+         * reset inode_ctx_reset1 and update local->cached_subvol
cb8e9e
+         * with the dst subvol.
cb8e9e
+         */
cb8e9e
+        if (!subvol)
cb8e9e
+                subvol = local->cached_subvol;
cb8e9e
+
cb8e9e
+        if (!subvol) {
cb8e9e
+                op_errno = EINVAL;
cb8e9e
+                goto err;
cb8e9e
+
cb8e9e
+        }
cb8e9e
+
cb8e9e
+
cb8e9e
+        local->call_cnt = 2; /* This is the second attempt */
cb8e9e
+
cb8e9e
+        if (local->fop == GF_FOP_REMOVEXATTR) {
cb8e9e
+                STACK_WIND (frame, dht_file_removexattr_cbk, subvol,
cb8e9e
+                            subvol->fops->removexattr, &local->loc,
cb8e9e
+                            local->key, NULL);
cb8e9e
+        } else {
cb8e9e
+                STACK_WIND (frame, dht_file_removexattr_cbk, subvol,
cb8e9e
+                            subvol->fops->fremovexattr, local->fd,
cb8e9e
+                            local->key, NULL);
cb8e9e
+        }
cb8e9e
+
cb8e9e
+        return 0;
cb8e9e
+
cb8e9e
+err:
cb8e9e
+        DHT_STACK_UNWIND (removexattr, frame, local->op_ret, op_errno, NULL);
cb8e9e
+        return 0;
cb8e9e
+}
cb8e9e
+
cb8e9e
+
cb8e9e
 int
cb8e9e
 dht_removexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
cb8e9e
                      int op_ret, int op_errno, dict_t *xdata)
cb8e9e
@@ -3631,6 +3940,8 @@ dht_removexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
cb8e9e
 unlock:
cb8e9e
         UNLOCK (&frame->lock);
cb8e9e
 
cb8e9e
+
cb8e9e
+
cb8e9e
         this_call_cnt = dht_frame_return (frame);
cb8e9e
         if (is_last_call (this_call_cnt)) {
cb8e9e
                 DHT_STACK_UNWIND (removexattr, frame, local->op_ret,
cb8e9e
@@ -3652,6 +3963,7 @@ dht_removexattr (call_frame_t *frame, xlator_t *this,
cb8e9e
         int           call_cnt = 0;
cb8e9e
         dht_conf_t   *conf = NULL;
cb8e9e
         int i;
cb8e9e
+        int           ret = 0;
cb8e9e
 
cb8e9e
         VALIDATE_OR_GOTO (this, err);
cb8e9e
         VALIDATE_OR_GOTO (this->private, err);
cb8e9e
@@ -3689,11 +4001,33 @@ dht_removexattr (call_frame_t *frame, xlator_t *this,
cb8e9e
         local->call_cnt = call_cnt = layout->cnt;
cb8e9e
         local->key = gf_strdup (key);
cb8e9e
 
cb8e9e
-        for (i = 0; i < call_cnt; i++) {
cb8e9e
-                STACK_WIND (frame, dht_removexattr_cbk,
cb8e9e
-                            layout->list[i].xlator,
cb8e9e
-                            layout->list[i].xlator->fops->removexattr,
cb8e9e
-                            loc, key, NULL);
cb8e9e
+        if (IA_ISDIR (loc->inode->ia_type)) {
cb8e9e
+                for (i = 0; i < call_cnt; i++) {
cb8e9e
+                        STACK_WIND (frame, dht_removexattr_cbk,
cb8e9e
+                                    layout->list[i].xlator,
cb8e9e
+                                    layout->list[i].xlator->fops->removexattr,
cb8e9e
+                                    loc, key, NULL);
cb8e9e
+                }
cb8e9e
+
cb8e9e
+        } else {
cb8e9e
+
cb8e9e
+                local->call_cnt = 1;
cb8e9e
+                xdata = xdata ? dict_ref (xdata) : dict_new ();
cb8e9e
+                if (xdata)
cb8e9e
+                        ret = dict_set_dynstr_with_alloc (xdata,
cb8e9e
+                                 DHT_IATT_IN_XDATA_KEY, "yes");
cb8e9e
+                if (ret) {
cb8e9e
+                        gf_log (this->name, GF_LOG_ERROR, "Failed to "
cb8e9e
+                                "set dictionary key %s for %s",
cb8e9e
+                                DHT_IATT_IN_XDATA_KEY, loc->path);
cb8e9e
+                }
cb8e9e
+
cb8e9e
+                STACK_WIND (frame, dht_file_removexattr_cbk,
cb8e9e
+                            subvol, subvol->fops->removexattr,
cb8e9e
+                            loc, key, xdata);
cb8e9e
+
cb8e9e
+                if (xdata)
cb8e9e
+                        dict_unref (xdata);
cb8e9e
         }
cb8e9e
 
cb8e9e
         return 0;
cb8e9e
@@ -3715,6 +4049,7 @@ dht_fremovexattr (call_frame_t *frame, xlator_t *this,
cb8e9e
         dht_layout_t *layout = NULL;
cb8e9e
         int           call_cnt = 0;
cb8e9e
         dht_conf_t   *conf = 0;
cb8e9e
+        int           ret = 0;
cb8e9e
 
cb8e9e
         int i;
cb8e9e
 
cb8e9e
@@ -3754,11 +4089,33 @@ dht_fremovexattr (call_frame_t *frame, xlator_t *this,
cb8e9e
         local->call_cnt = call_cnt = layout->cnt;
cb8e9e
         local->key = gf_strdup (key);
cb8e9e
 
cb8e9e
-        for (i = 0; i < call_cnt; i++) {
cb8e9e
-                STACK_WIND (frame, dht_removexattr_cbk,
cb8e9e
-                            layout->list[i].xlator,
cb8e9e
-                            layout->list[i].xlator->fops->fremovexattr,
cb8e9e
-                            fd, key, NULL);
cb8e9e
+        if (IA_ISDIR (fd->inode->ia_type)) {
cb8e9e
+                for (i = 0; i < call_cnt; i++) {
cb8e9e
+                        STACK_WIND (frame, dht_removexattr_cbk,
cb8e9e
+                                    layout->list[i].xlator,
cb8e9e
+                                    layout->list[i].xlator->fops->fremovexattr,
cb8e9e
+                                    fd, key, NULL);
cb8e9e
+                }
cb8e9e
+
cb8e9e
+        } else {
cb8e9e
+
cb8e9e
+                local->call_cnt = 1;
cb8e9e
+                xdata = xdata ? dict_ref (xdata) : dict_new ();
cb8e9e
+                if (xdata)
cb8e9e
+                        ret = dict_set_dynstr_with_alloc (xdata,
cb8e9e
+                                 DHT_IATT_IN_XDATA_KEY, "yes");
cb8e9e
+                if (ret) {
cb8e9e
+                        gf_log (this->name, GF_LOG_ERROR, "Failed to "
cb8e9e
+                                "set dictionary key %s for fd=%p",
cb8e9e
+                                DHT_IATT_IN_XDATA_KEY, fd);
cb8e9e
+                }
cb8e9e
+
cb8e9e
+                STACK_WIND (frame, dht_file_removexattr_cbk,
cb8e9e
+                            subvol, subvol->fops->fremovexattr,
cb8e9e
+                            fd, key, xdata);
cb8e9e
+
cb8e9e
+                if (xdata)
cb8e9e
+                        dict_unref (xdata);
cb8e9e
         }
cb8e9e
 
cb8e9e
         return 0;
cb8e9e
diff --git a/xlators/cluster/ec/src/ec-combine.c b/xlators/cluster/ec/src/ec-combine.c
cb8e9e
index 6395b22..a8cfabc 100644
cb8e9e
--- a/xlators/cluster/ec/src/ec-combine.c
cb8e9e
+++ b/xlators/cluster/ec/src/ec-combine.c
cb8e9e
@@ -246,6 +246,7 @@ ec_value_ignore (char *key)
cb8e9e
             (strcmp(key, GLUSTERFS_ENTRYLK_COUNT) == 0) ||
cb8e9e
             (strncmp(key, GF_XATTR_CLRLK_CMD,
cb8e9e
                      strlen (GF_XATTR_CLRLK_CMD)) == 0) ||
cb8e9e
+            (strcmp(key, DHT_IATT_IN_XDATA_KEY) == 0) ||
cb8e9e
             (strncmp(key, EC_QUOTA_PREFIX, strlen(EC_QUOTA_PREFIX)) == 0) ||
cb8e9e
             (fnmatch(MARKER_XATTR_PREFIX ".*." XTIME, key, 0) == 0) ||
cb8e9e
             (fnmatch(GF_XATTR_MARKER_KEY ".*", key, 0) == 0) ||
cb8e9e
diff --git a/xlators/storage/posix/src/posix.c b/xlators/storage/posix/src/posix.c
cb8e9e
index fbbeacd..71b83c2 100644
cb8e9e
--- a/xlators/storage/posix/src/posix.c
cb8e9e
+++ b/xlators/storage/posix/src/posix.c
cb8e9e
@@ -3239,6 +3239,31 @@ map_xattr_flags(int flags)
cb8e9e
 }
cb8e9e
 #endif
cb8e9e
 
cb8e9e
+static
cb8e9e
+int32_t posix_set_iatt_in_dict (dict_t *dict, struct iatt *in_stbuf)
cb8e9e
+{
cb8e9e
+        int ret             = -1;
cb8e9e
+        struct iatt *stbuf  = NULL;
cb8e9e
+        int32_t len         = sizeof(struct iatt);
cb8e9e
+
cb8e9e
+        if (!dict || !in_stbuf)
cb8e9e
+                return ret;
cb8e9e
+
cb8e9e
+        stbuf = GF_CALLOC (1, len, gf_common_mt_char);
cb8e9e
+        if (!stbuf)
cb8e9e
+                return ret;
cb8e9e
+
cb8e9e
+        memcpy (stbuf, in_stbuf, len);
cb8e9e
+
cb8e9e
+        ret = dict_set_bin (dict, DHT_IATT_IN_XDATA_KEY, stbuf, len);
cb8e9e
+        if (ret)
cb8e9e
+                GF_FREE (stbuf);
cb8e9e
+
cb8e9e
+        return ret;
cb8e9e
+}
cb8e9e
+
cb8e9e
+
cb8e9e
+
cb8e9e
 int32_t
cb8e9e
 posix_setxattr (call_frame_t *frame, xlator_t *this,
cb8e9e
                 loc_t *loc, dict_t *dict, int flags, dict_t *xdata)
cb8e9e
@@ -3246,7 +3271,9 @@ posix_setxattr (call_frame_t *frame, xlator_t *this,
cb8e9e
         int32_t       op_ret                  = -1;
cb8e9e
         int32_t       op_errno                = 0;
cb8e9e
         char *        real_path               = NULL;
cb8e9e
-
cb8e9e
+        struct iatt   stbuf                   = {0};
cb8e9e
+        int32_t       ret                     = 0;
cb8e9e
+        dict_t       *xattr                   = NULL;
cb8e9e
         posix_xattr_filler_t filler = {0,};
cb8e9e
 
cb8e9e
         DECLARE_OLD_FS_ID_VAR;
cb8e9e
@@ -3265,6 +3292,7 @@ posix_setxattr (call_frame_t *frame, xlator_t *this,
cb8e9e
         }
cb8e9e
 
cb8e9e
         op_ret = -1;
cb8e9e
+
cb8e9e
         dict_del (dict, GFID_XATTR_KEY);
cb8e9e
         dict_del (dict, GF_XATTR_VOL_ID_KEY);
cb8e9e
 
cb8e9e
@@ -3280,12 +3308,31 @@ posix_setxattr (call_frame_t *frame, xlator_t *this,
cb8e9e
         if (op_ret < 0) {
cb8e9e
                 op_errno = -op_ret;
cb8e9e
                 op_ret = -1;
cb8e9e
+                goto out;
cb8e9e
         }
cb8e9e
 
cb8e9e
+/*
cb8e9e
+ * FIXFIX: Send the stbuf info in the xdata for now
cb8e9e
+ * This is used by DHT to redirect FOPs if the file is being migrated
cb8e9e
+ * Ignore errors for now
cb8e9e
+ */
cb8e9e
+        if (dict_get (xdata, DHT_IATT_IN_XDATA_KEY)) {
cb8e9e
+                ret = posix_pstat(this, loc->gfid, real_path, &stbuf);
cb8e9e
+                if (ret)
cb8e9e
+                        goto out;
cb8e9e
+
cb8e9e
+                xattr = dict_new();
cb8e9e
+                if (!xattr)
cb8e9e
+                        goto out;
cb8e9e
+                ret = posix_set_iatt_in_dict (xattr, &stbuf);
cb8e9e
+        }
cb8e9e
 out:
cb8e9e
         SET_TO_OLD_FS_ID ();
cb8e9e
 
cb8e9e
-        STACK_UNWIND_STRICT (setxattr, frame, op_ret, op_errno, NULL);
cb8e9e
+        STACK_UNWIND_STRICT (setxattr, frame, op_ret, op_errno, xattr);
cb8e9e
+
cb8e9e
+        if (xattr)
cb8e9e
+                dict_unref(xattr);
cb8e9e
 
cb8e9e
         return 0;
cb8e9e
 }
cb8e9e
@@ -4313,13 +4360,14 @@ int32_t
cb8e9e
 posix_fsetxattr (call_frame_t *frame, xlator_t *this,
cb8e9e
                  fd_t *fd, dict_t *dict, int flags, dict_t *xdata)
cb8e9e
 {
cb8e9e
-        int32_t            op_ret       = -1;
cb8e9e
-        int32_t            op_errno     = 0;
cb8e9e
-        struct posix_fd *  pfd          = NULL;
cb8e9e
-        int                _fd          = -1;
cb8e9e
-        int                ret          = -1;
cb8e9e
-
cb8e9e
-        posix_xattr_filler_t filler = {0,};
cb8e9e
+        int32_t            op_ret         = -1;
cb8e9e
+        int32_t            op_errno       = 0;
cb8e9e
+        struct posix_fd   *pfd            = NULL;
cb8e9e
+        int                _fd            = -1;
cb8e9e
+        int                ret            = -1;
cb8e9e
+        struct  iatt       stbuf          = {0,};
cb8e9e
+        dict_t            *xattr          = NULL;
cb8e9e
+        posix_xattr_filler_t filler       = {0,};
cb8e9e
 
cb8e9e
         DECLARE_OLD_FS_ID_VAR;
cb8e9e
         SET_FS_ID (frame->root->uid, frame->root->gid);
cb8e9e
@@ -4366,10 +4414,28 @@ posix_fsetxattr (call_frame_t *frame, xlator_t *this,
cb8e9e
                 }
cb8e9e
         }
cb8e9e
 
cb8e9e
+        if (dict_get (xdata, DHT_IATT_IN_XDATA_KEY)) {
cb8e9e
+                ret = posix_fdstat (this, pfd->fd, &stbuf);
cb8e9e
+                if (ret == -1) {
cb8e9e
+                        gf_log (this->name, GF_LOG_ERROR,
cb8e9e
+                                "fsetxattr (fstat) failed on fd=%p: %s",
cb8e9e
+                                fd, strerror (op_errno));
cb8e9e
+                        goto out;
cb8e9e
+                }
cb8e9e
+
cb8e9e
+                xattr = dict_new ();
cb8e9e
+                if (!xattr)
cb8e9e
+                        goto out;
cb8e9e
+                ret = posix_set_iatt_in_dict (xattr, &stbuf);
cb8e9e
+        }
cb8e9e
+
cb8e9e
 out:
cb8e9e
         SET_TO_OLD_FS_ID ();
cb8e9e
 
cb8e9e
-        STACK_UNWIND_STRICT (fsetxattr, frame, op_ret, op_errno, NULL);
cb8e9e
+        STACK_UNWIND_STRICT (fsetxattr, frame, op_ret, op_errno, xattr);
cb8e9e
+
cb8e9e
+        if (xattr)
cb8e9e
+                dict_unref (xattr);
cb8e9e
 
cb8e9e
         return 0;
cb8e9e
 }
cb8e9e
@@ -4429,7 +4495,10 @@ posix_removexattr (call_frame_t *frame, xlator_t *this,
cb8e9e
 {
cb8e9e
         int32_t op_ret    = -1;
cb8e9e
         int32_t op_errno  = 0;
cb8e9e
+        int32_t ret    = -1;
cb8e9e
         char *  real_path = NULL;
cb8e9e
+        struct iatt   stbuf         = {0};
cb8e9e
+        dict_t  *xattr    = NULL;
cb8e9e
         posix_xattr_filler_t filler = {0,};
cb8e9e
 
cb8e9e
         DECLARE_OLD_FS_ID_VAR;
cb8e9e
@@ -4485,12 +4554,26 @@ posix_removexattr (call_frame_t *frame, xlator_t *this,
cb8e9e
                 goto out;
cb8e9e
         }
cb8e9e
 
cb8e9e
+        if (dict_get (xdata, DHT_IATT_IN_XDATA_KEY)) {
cb8e9e
+                ret = posix_pstat(this, loc->gfid, real_path, &stbuf);
cb8e9e
+                if (ret)
cb8e9e
+                        goto out;
cb8e9e
+                xattr = dict_new();
cb8e9e
+                if (!xattr)
cb8e9e
+                        goto out;
cb8e9e
+
cb8e9e
+                ret = posix_set_iatt_in_dict (xattr, &stbuf);
cb8e9e
+        }
cb8e9e
         op_ret = 0;
cb8e9e
 
cb8e9e
 out:
cb8e9e
         SET_TO_OLD_FS_ID ();
cb8e9e
 
cb8e9e
-        STACK_UNWIND_STRICT (removexattr, frame, op_ret, op_errno, NULL);
cb8e9e
+        STACK_UNWIND_STRICT (removexattr, frame, op_ret, op_errno, xattr);
cb8e9e
+
cb8e9e
+        if (xattr)
cb8e9e
+                dict_unref (xattr);
cb8e9e
+
cb8e9e
         return 0;
cb8e9e
 }
cb8e9e
 
cb8e9e
@@ -4501,6 +4584,8 @@ posix_fremovexattr (call_frame_t *frame, xlator_t *this,
cb8e9e
         int32_t           op_ret   = -1;
cb8e9e
         int32_t           op_errno = 0;
cb8e9e
         struct posix_fd * pfd      = NULL;
cb8e9e
+        struct iatt       stbuf    = {0,};
cb8e9e
+        dict_t           *xattr    = NULL;
cb8e9e
         int               _fd      = -1;
cb8e9e
         int               ret      = -1;
cb8e9e
 
cb8e9e
@@ -4541,12 +4626,26 @@ posix_fremovexattr (call_frame_t *frame, xlator_t *this,
cb8e9e
                 goto out;
cb8e9e
         }
cb8e9e
 
cb8e9e
+        if (dict_get (xdata, DHT_IATT_IN_XDATA_KEY)) {
cb8e9e
+                ret = posix_fdstat (this, pfd->fd, &stbuf);
cb8e9e
+                if (ret)
cb8e9e
+                        goto out;
cb8e9e
+                xattr = dict_new();
cb8e9e
+                if (!xattr)
cb8e9e
+                        goto out;
cb8e9e
+
cb8e9e
+                ret = posix_set_iatt_in_dict (xattr, &stbuf);
cb8e9e
+        }
cb8e9e
         op_ret = 0;
cb8e9e
 
cb8e9e
 out:
cb8e9e
         SET_TO_OLD_FS_ID ();
cb8e9e
 
cb8e9e
-        STACK_UNWIND_STRICT (fremovexattr, frame, op_ret, op_errno, NULL);
cb8e9e
+        STACK_UNWIND_STRICT (fremovexattr, frame, op_ret, op_errno, xattr);
cb8e9e
+
cb8e9e
+        if (xattr)
cb8e9e
+                dict_unref (xattr);
cb8e9e
+
cb8e9e
         return 0;
cb8e9e
 }
cb8e9e
 
cb8e9e
-- 
cb8e9e
1.9.3
cb8e9e