e3c68b
From 90254e4ae9455fa0a126f83700978a9314eb79ea Mon Sep 17 00:00:00 2001
e3c68b
From: Anuradha Talur <atalur@commvault.com>
e3c68b
Date: Thu, 29 Nov 2018 12:54:21 -0800
e3c68b
Subject: [PATCH 153/169] features/cloudsync : Added some new functions
e3c68b
e3c68b
This patch contains the following changes:
e3c68b
1) Store ID info will now be stored in the inode ctx
e3c68b
2) Added new readv type where read is made directly
e3c68b
   from the remote store. This choice is made by
e3c68b
   volume set operation.
e3c68b
3) cs_forget() was missing. Added it.
e3c68b
e3c68b
backport of:https://review.gluster.org/#/c/glusterfs/+/21757/
e3c68b
e3c68b
> Change-Id: Ie3232b3d7ffb5313a03f011b0553b19793eedfa2
e3c68b
> fixes: bz#1642168
e3c68b
> Signed-off-by: Anuradha Talur <atalur@commvault.com>
e3c68b
e3c68b
Change-Id: I089e5a8c93049cf6bfabf011673796e38e78d7ee
e3c68b
Signed-off-by: Susant Palai <spalai@redhat.com>
e3c68b
Reviewed-on: https://code.engineering.redhat.com/gerrit/172192
e3c68b
Tested-by: RHGS Build Bot <nigelb@redhat.com>
e3c68b
Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
e3c68b
---
e3c68b
 xlators/features/cloudsync/src/cloudsync-common.c  |  16 +
e3c68b
 xlators/features/cloudsync/src/cloudsync-common.h  |  35 ++
e3c68b
 xlators/features/cloudsync/src/cloudsync-fops-c.py |  12 +-
e3c68b
 .../features/cloudsync/src/cloudsync-mem-types.h   |   1 +
e3c68b
 xlators/features/cloudsync/src/cloudsync.c         | 600 ++++++++++++++++++---
e3c68b
 xlators/features/cloudsync/src/cloudsync.h         |  20 +
e3c68b
 xlators/mgmt/glusterd/src/glusterd-volume-set.c    |   7 +-
e3c68b
 7 files changed, 597 insertions(+), 94 deletions(-)
e3c68b
e3c68b
diff --git a/xlators/features/cloudsync/src/cloudsync-common.c b/xlators/features/cloudsync/src/cloudsync-common.c
e3c68b
index aee1f06..445a31b 100644
e3c68b
--- a/xlators/features/cloudsync/src/cloudsync-common.c
e3c68b
+++ b/xlators/features/cloudsync/src/cloudsync-common.c
e3c68b
@@ -11,6 +11,20 @@
e3c68b
 #include "cloudsync-common.h"
e3c68b
 
e3c68b
 void
e3c68b
+cs_xattrinfo_wipe(cs_local_t *local)
e3c68b
+{
e3c68b
+    if (local->xattrinfo.lxattr) {
e3c68b
+        if (local->xattrinfo.lxattr->file_path)
e3c68b
+            GF_FREE(local->xattrinfo.lxattr->file_path);
e3c68b
+
e3c68b
+        if (local->xattrinfo.lxattr->volname)
e3c68b
+            GF_FREE(local->xattrinfo.lxattr->volname);
e3c68b
+
e3c68b
+        GF_FREE(local->xattrinfo.lxattr);
e3c68b
+    }
e3c68b
+}
e3c68b
+
e3c68b
+void
e3c68b
 cs_local_wipe(xlator_t *this, cs_local_t *local)
e3c68b
 {
e3c68b
     if (!local)
e3c68b
@@ -40,5 +54,7 @@ cs_local_wipe(xlator_t *this, cs_local_t *local)
e3c68b
     if (local->remotepath)
e3c68b
         GF_FREE(local->remotepath);
e3c68b
 
e3c68b
+    cs_xattrinfo_wipe(local);
e3c68b
+
e3c68b
     mem_put(local);
e3c68b
 }
e3c68b
diff --git a/xlators/features/cloudsync/src/cloudsync-common.h b/xlators/features/cloudsync/src/cloudsync-common.h
e3c68b
index 7b3520c..11d2334 100644
e3c68b
--- a/xlators/features/cloudsync/src/cloudsync-common.h
e3c68b
+++ b/xlators/features/cloudsync/src/cloudsync-common.h
e3c68b
@@ -14,9 +14,23 @@
e3c68b
 #include <glusterfs/call-stub.h>
e3c68b
 #include <glusterfs/xlator.h>
e3c68b
 #include <glusterfs/syncop.h>
e3c68b
+#include <glusterfs/compat-errno.h>
e3c68b
 #include "cloudsync-mem-types.h"
e3c68b
 #include "cloudsync-messages.h"
e3c68b
 
e3c68b
+typedef struct cs_loc_xattr {
e3c68b
+    char *file_path;
e3c68b
+    uuid_t uuid;
e3c68b
+    uuid_t gfid;
e3c68b
+    char *volname;
e3c68b
+} cs_loc_xattr_t;
e3c68b
+
e3c68b
+typedef struct cs_size_xattr {
e3c68b
+    uint64_t size;
e3c68b
+    uint64_t blksize;
e3c68b
+    uint64_t blocks;
e3c68b
+} cs_size_xattr_t;
e3c68b
+
e3c68b
 typedef struct cs_local {
e3c68b
     loc_t loc;
e3c68b
     fd_t *fd;
e3c68b
@@ -34,10 +48,25 @@ typedef struct cs_local {
e3c68b
     int call_cnt;
e3c68b
     inode_t *inode;
e3c68b
     char *remotepath;
e3c68b
+
e3c68b
+    struct {
e3c68b
+        /* offset, flags and size are the information needed
e3c68b
+         * by read fop for remote read operation. These will be
e3c68b
+         * populated in cloudsync read fop, before being passed
e3c68b
+         * on to the plugin performing remote read.
e3c68b
+         */
e3c68b
+        off_t offset;
e3c68b
+        uint32_t flags;
e3c68b
+        size_t size;
e3c68b
+        cs_loc_xattr_t *lxattr;
e3c68b
+    } xattrinfo;
e3c68b
+
e3c68b
 } cs_local_t;
e3c68b
 
e3c68b
 typedef int (*fop_download_t)(call_frame_t *frame, void *config);
e3c68b
 
e3c68b
+typedef int (*fop_remote_read_t)(call_frame_t *, void *);
e3c68b
+
e3c68b
 typedef void *(*store_init)(xlator_t *this);
e3c68b
 
e3c68b
 typedef int (*store_reconfigure)(xlator_t *this, dict_t *options);
e3c68b
@@ -48,6 +77,7 @@ struct cs_remote_stores {
e3c68b
     char *name;                    /* store name */
e3c68b
     void *config;                  /* store related information */
e3c68b
     fop_download_t dlfop;          /* store specific download function */
e3c68b
+    fop_remote_read_t rdfop;       /* store specific read function */
e3c68b
     store_init init;               /* store init to initialize store config */
e3c68b
     store_reconfigure reconfigure; /* reconfigure store config */
e3c68b
     store_fini fini;
e3c68b
@@ -59,11 +89,15 @@ typedef struct cs_private {
e3c68b
     struct cs_remote_stores *stores;
e3c68b
     gf_boolean_t abortdl;
e3c68b
     pthread_spinlock_t lock;
e3c68b
+    gf_boolean_t remote_read;
e3c68b
 } cs_private_t;
e3c68b
 
e3c68b
 void
e3c68b
 cs_local_wipe(xlator_t *this, cs_local_t *local);
e3c68b
 
e3c68b
+void
e3c68b
+cs_xattrinfo_wipe(cs_local_t *local);
e3c68b
+
e3c68b
 #define CS_STACK_UNWIND(fop, frame, params...)                                 \
e3c68b
     do {                                                                       \
e3c68b
         cs_local_t *__local = NULL;                                            \
e3c68b
@@ -90,6 +124,7 @@ cs_local_wipe(xlator_t *this, cs_local_t *local);
e3c68b
 
e3c68b
 typedef struct store_methods {
e3c68b
     int (*fop_download)(call_frame_t *frame, void *config);
e3c68b
+    int (*fop_remote_read)(call_frame_t *, void *);
e3c68b
     /* return type should be the store config */
e3c68b
     void *(*fop_init)(xlator_t *this);
e3c68b
     int (*fop_reconfigure)(xlator_t *this, dict_t *options);
e3c68b
diff --git a/xlators/features/cloudsync/src/cloudsync-fops-c.py b/xlators/features/cloudsync/src/cloudsync-fops-c.py
e3c68b
index 3122bd3..a7a2201 100755
e3c68b
--- a/xlators/features/cloudsync/src/cloudsync-fops-c.py
e3c68b
+++ b/xlators/features/cloudsync/src/cloudsync-fops-c.py
e3c68b
@@ -137,15 +137,15 @@ cs_@NAME@_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
e3c68b
                         } else {
e3c68b
                                 __cs_inode_ctx_update (this, fd->inode, val);
e3c68b
                                 gf_msg (this->name, GF_LOG_INFO, 0, 0,
e3c68b
-                                        " state = %ld", val);
e3c68b
+                                        " state = %" PRIu64, val);
e3c68b
 
e3c68b
                                 if (local->call_cnt == 1 &&
e3c68b
                                     (val == GF_CS_REMOTE ||
e3c68b
                                      val == GF_CS_DOWNLOADING))  {
e3c68b
                                         gf_msg (this->name, GF_LOG_INFO, 0,
e3c68b
                                                 0, " will repair and download "
e3c68b
-                                                "the file, current state : %ld",
e3c68b
-                                                val);
e3c68b
+                                                "the file, current state : %"
e3c68b
+                                                PRIu64, val);
e3c68b
                                         goto repair;
e3c68b
                                 } else {
e3c68b
                                         gf_msg (this->name, GF_LOG_ERROR, 0, 0,
e3c68b
@@ -274,7 +274,7 @@ fd_ops = ['readv', 'writev', 'flush', 'fsync', 'fsyncdir', 'ftruncate',
e3c68b
 # These are the current actual lists used to generate the code
e3c68b
 
e3c68b
 # The following list contains fops which are fd based that modifies data
e3c68b
-fd_data_modify_op_fop_template = ['readv', 'writev', 'flush', 'fsync',
e3c68b
+fd_data_modify_op_fop_template = ['writev', 'flush', 'fsync',
e3c68b
                                   'ftruncate', 'rchecksum', 'fallocate',
e3c68b
                                   'discard', 'zerofill', 'seek']
e3c68b
 
e3c68b
@@ -284,8 +284,8 @@ loc_stat_op_fop_template = ['lookup', 'stat', 'discover', 'access', 'setattr',
e3c68b
                             'getattr']
e3c68b
 
e3c68b
 # These fops need a separate implementation
e3c68b
-special_fops = ['readdirp', 'statfs', 'setxattr', 'unlink', 'getxattr',
e3c68b
-                'truncate', 'fstat']
e3c68b
+special_fops = ['statfs', 'setxattr', 'unlink', 'getxattr',
e3c68b
+                'truncate', 'fstat', 'readv']
e3c68b
 
e3c68b
 def gen_defaults():
e3c68b
     for name in ops:
e3c68b
diff --git a/xlators/features/cloudsync/src/cloudsync-mem-types.h b/xlators/features/cloudsync/src/cloudsync-mem-types.h
e3c68b
index 9e6837a..2203464 100644
e3c68b
--- a/xlators/features/cloudsync/src/cloudsync-mem-types.h
e3c68b
+++ b/xlators/features/cloudsync/src/cloudsync-mem-types.h
e3c68b
@@ -16,6 +16,7 @@ enum cs_mem_types_ {
e3c68b
     gf_cs_mt_cs_private_t = gf_common_mt_end + 1,
e3c68b
     gf_cs_mt_cs_remote_stores_t,
e3c68b
     gf_cs_mt_cs_inode_ctx_t,
e3c68b
+    gf_cs_mt_cs_lxattr_t,
e3c68b
     gf_cs_mt_end
e3c68b
 };
e3c68b
 #endif /* __CLOUDSYNC_MEM_TYPES_H__ */
e3c68b
diff --git a/xlators/features/cloudsync/src/cloudsync.c b/xlators/features/cloudsync/src/cloudsync.c
e3c68b
index fbdcdf7..2240fc3 100644
e3c68b
--- a/xlators/features/cloudsync/src/cloudsync.c
e3c68b
+++ b/xlators/features/cloudsync/src/cloudsync.c
e3c68b
@@ -16,6 +16,7 @@
e3c68b
 #include <glusterfs/call-stub.h>
e3c68b
 #include "cloudsync-autogen-fops.h"
e3c68b
 
e3c68b
+#include <string.h>
e3c68b
 #include <dlfcn.h>
e3c68b
 
e3c68b
 void
e3c68b
@@ -72,6 +73,8 @@ cs_init(xlator_t *this)
e3c68b
 
e3c68b
     this->private = priv;
e3c68b
 
e3c68b
+    GF_OPTION_INIT("cloudsync-remote-read", priv->remote_read, bool, out);
e3c68b
+
e3c68b
     /* temp workaround. Should be configurable through glusterd*/
e3c68b
     per_vol = _gf_true;
e3c68b
 
e3c68b
@@ -135,6 +138,18 @@ cs_init(xlator_t *this)
e3c68b
 
e3c68b
         (void)dlerror();
e3c68b
 
e3c68b
+        if (priv->remote_read) {
e3c68b
+            priv->stores->rdfop = store_methods->fop_remote_read;
e3c68b
+            if (!priv->stores->rdfop) {
e3c68b
+                gf_msg(this->name, GF_LOG_ERROR, 0, 0,
e3c68b
+                       "failed to get"
e3c68b
+                       " read fop %s",
e3c68b
+                       dlerror());
e3c68b
+                ret = -1;
e3c68b
+                goto out;
e3c68b
+            }
e3c68b
+        }
e3c68b
+
e3c68b
         priv->stores->dlfop = store_methods->fop_download;
e3c68b
         if (!priv->stores->dlfop) {
e3c68b
             gf_msg(this->name, GF_LOG_ERROR, 0, 0,
e3c68b
@@ -196,6 +211,22 @@ out:
e3c68b
     return ret;
e3c68b
 }
e3c68b
 
e3c68b
+int
e3c68b
+cs_forget(xlator_t *this, inode_t *inode)
e3c68b
+{
e3c68b
+    uint64_t ctx_int = 0;
e3c68b
+    cs_inode_ctx_t *ctx = NULL;
e3c68b
+
e3c68b
+    inode_ctx_del(inode, this, &ctx_int);
e3c68b
+    if (!ctx_int)
e3c68b
+        return 0;
e3c68b
+
e3c68b
+    ctx = (cs_inode_ctx_t *)(uintptr_t)ctx_int;
e3c68b
+
e3c68b
+    GF_FREE(ctx);
e3c68b
+    return 0;
e3c68b
+}
e3c68b
+
e3c68b
 void
e3c68b
 cs_fini(xlator_t *this)
e3c68b
 {
e3c68b
@@ -217,6 +248,9 @@ cs_reconfigure(xlator_t *this, dict_t *options)
e3c68b
         goto out;
e3c68b
     }
e3c68b
 
e3c68b
+    GF_OPTION_RECONF("cloudsync-remote-read", priv->remote_read, options, bool,
e3c68b
+                     out);
e3c68b
+
e3c68b
     /* needed only for per volume configuration*/
e3c68b
     ret = priv->stores->reconfigure(this, options);
e3c68b
 
e3c68b
@@ -242,59 +276,6 @@ out:
e3c68b
 }
e3c68b
 
e3c68b
 int32_t
e3c68b
-cs_readdirp_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
e3c68b
-                int32_t op_ret, int32_t op_errno, gf_dirent_t *entries,
e3c68b
-                dict_t *xdata)
e3c68b
-{
e3c68b
-    gf_dirent_t *tmp = NULL;
e3c68b
-    char *sxattr = NULL;
e3c68b
-    uint64_t ia_size = 0;
e3c68b
-    int ret = 0;
e3c68b
-
e3c68b
-    list_for_each_entry(tmp, &entries->list, list)
e3c68b
-    {
e3c68b
-        ret = dict_get_str(tmp->dict, GF_CS_OBJECT_SIZE, &sxattr);
e3c68b
-        if (ret) {
e3c68b
-            gf_msg_trace(this->name, 0, "size xattr found");
e3c68b
-            continue;
e3c68b
-        }
e3c68b
-
e3c68b
-        ia_size = atoll(sxattr);
e3c68b
-        tmp->d_stat.ia_size = ia_size;
e3c68b
-    }
e3c68b
-
e3c68b
-    STACK_UNWIND_STRICT(readdirp, frame, op_ret, op_errno, entries, xdata);
e3c68b
-    return 0;
e3c68b
-}
e3c68b
-
e3c68b
-int32_t
e3c68b
-cs_readdirp(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size,
e3c68b
-            off_t off, dict_t *xdata)
e3c68b
-{
e3c68b
-    int ret = 0;
e3c68b
-    int op_errno = ENOMEM;
e3c68b
-
e3c68b
-    if (!xdata) {
e3c68b
-        xdata = dict_new();
e3c68b
-        if (!xdata) {
e3c68b
-            goto err;
e3c68b
-        }
e3c68b
-    }
e3c68b
-
e3c68b
-    ret = dict_set_int32(xdata, GF_CS_OBJECT_SIZE, 1);
e3c68b
-    if (ret) {
e3c68b
-        goto err;
e3c68b
-    }
e3c68b
-
e3c68b
-    STACK_WIND(frame, cs_readdirp_cbk, FIRST_CHILD(this),
e3c68b
-               FIRST_CHILD(this)->fops->readdirp, fd, size, off, xdata);
e3c68b
-    return 0;
e3c68b
-err:
e3c68b
-    STACK_UNWIND_STRICT(readdirp, frame, -1, op_errno, NULL, NULL);
e3c68b
-    return 0;
e3c68b
-}
e3c68b
-
e3c68b
-int32_t
e3c68b
 cs_truncate_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
e3c68b
                 int32_t op_ret, int32_t op_errno, struct iatt *prebuf,
e3c68b
                 struct iatt *postbuf, dict_t *xdata)
e3c68b
@@ -305,7 +286,6 @@ cs_truncate_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
e3c68b
 
e3c68b
     local = frame->local;
e3c68b
 
e3c68b
-    /* Do we need lock here? */
e3c68b
     local->call_cnt++;
e3c68b
 
e3c68b
     if (op_ret == -1) {
e3c68b
@@ -320,13 +300,13 @@ cs_truncate_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
e3c68b
                 goto unwind;
e3c68b
             } else {
e3c68b
                 __cs_inode_ctx_update(this, local->loc.inode, val);
e3c68b
-                gf_msg(this->name, GF_LOG_INFO, 0, 0, " state = %ld", val);
e3c68b
+                gf_msg(this->name, GF_LOG_INFO, 0, 0, " state = %" PRIu64, val);
e3c68b
 
e3c68b
                 if (local->call_cnt == 1 &&
e3c68b
                     (val == GF_CS_REMOTE || val == GF_CS_DOWNLOADING)) {
e3c68b
                     gf_msg(this->name, GF_LOG_WARNING, 0, 0,
e3c68b
                            "will repair and download "
e3c68b
-                           "the file, current state : %ld",
e3c68b
+                           "the file, current state : %" PRIu64,
e3c68b
                            val);
e3c68b
                     goto repair;
e3c68b
                 } else {
e3c68b
@@ -665,7 +645,7 @@ cs_fstat_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret,
e3c68b
     if (op_ret == 0) {
e3c68b
         ret = dict_get_uint64(xdata, GF_CS_OBJECT_STATUS, &val;;
e3c68b
         if (!ret) {
e3c68b
-            gf_msg_debug(this->name, 0, "state %ld", val);
e3c68b
+            gf_msg_debug(this->name, 0, "state %" PRIu64, val);
e3c68b
             ret = __cs_inode_ctx_update(this, fd->inode, val);
e3c68b
             if (ret) {
e3c68b
                 gf_msg(this->name, GF_LOG_ERROR, 0, 0, "ctx update failed");
e3c68b
@@ -831,7 +811,7 @@ out:
e3c68b
     return 0;
e3c68b
 }
e3c68b
 
e3c68b
-void *
e3c68b
+int
e3c68b
 cs_download_task(void *arg)
e3c68b
 {
e3c68b
     call_frame_t *frame = NULL;
e3c68b
@@ -842,7 +822,6 @@ cs_download_task(void *arg)
e3c68b
     fd_t *fd = NULL;
e3c68b
     cs_local_t *local = NULL;
e3c68b
     dict_t *dict = NULL;
e3c68b
-    int *retval = NULL;
e3c68b
 
e3c68b
     frame = (call_frame_t *)arg;
e3c68b
 
e3c68b
@@ -850,13 +829,6 @@ cs_download_task(void *arg)
e3c68b
 
e3c68b
     priv = this->private;
e3c68b
 
e3c68b
-    retval = GF_CALLOC(1, sizeof(int), gf_common_mt_int);
e3c68b
-    if (!retval) {
e3c68b
-        gf_msg(this->name, GF_LOG_ERROR, 0, 0, "insufficient memory");
e3c68b
-        ret = -1;
e3c68b
-        goto out;
e3c68b
-    }
e3c68b
-
e3c68b
     if (!priv->stores) {
e3c68b
         gf_msg(this->name, GF_LOG_ERROR, 0, 0,
e3c68b
                "No remote store "
e3c68b
@@ -972,20 +944,13 @@ out:
e3c68b
         local->dlfd = NULL;
e3c68b
     }
e3c68b
 
e3c68b
-    if (retval) {
e3c68b
-        *retval = ret;
e3c68b
-        pthread_exit(retval);
e3c68b
-    } else {
e3c68b
-        pthread_exit(&ret;;
e3c68b
-    }
e3c68b
+    return ret;
e3c68b
 }
e3c68b
 
e3c68b
 int
e3c68b
 cs_download(call_frame_t *frame)
e3c68b
 {
e3c68b
-    int *retval = NULL;
e3c68b
     int ret = 0;
e3c68b
-    pthread_t dthread;
e3c68b
     cs_local_t *local = NULL;
e3c68b
     xlator_t *this = NULL;
e3c68b
 
e3c68b
@@ -1000,16 +965,406 @@ cs_download(call_frame_t *frame)
e3c68b
         goto out;
e3c68b
     }
e3c68b
 
e3c68b
-    ret = gf_thread_create(&dthread, NULL, &cs_download_task, (void *)frame,
e3c68b
-                           "downloadthread");
e3c68b
+    ret = cs_download_task((void *)frame);
e3c68b
+out:
e3c68b
+    return ret;
e3c68b
+}
e3c68b
 
e3c68b
-    pthread_join(dthread, (void **)&retval);
e3c68b
+int
e3c68b
+cs_set_xattr_req(call_frame_t *frame)
e3c68b
+{
e3c68b
+    cs_local_t *local = NULL;
e3c68b
+    GF_UNUSED int ret = 0;
e3c68b
+
e3c68b
+    local = frame->local;
e3c68b
+
e3c68b
+    /* When remote reads are performed (i.e. reads on remote store),
e3c68b
+     * there needs to be a way to associate a file on gluster volume
e3c68b
+     * with its correspnding file on the remote store. In order to do
e3c68b
+     * that, a unique key can be maintained as an xattr
e3c68b
+     * (GF_CS_XATTR_ARCHIVE_UUID)on the stub file on gluster bricks.
e3c68b
+     * This xattr should be provided to the plugin to
e3c68b
+     * perform the read fop on the correct file. This assumes that the file
e3c68b
+     * hierarchy and name need not be the same on remote store as that of
e3c68b
+     * the gluster volume.
e3c68b
+     */
e3c68b
+    ret = dict_set_str(local->xattr_req, GF_CS_XATTR_ARCHIVE_UUID, "1");
e3c68b
+
e3c68b
+    return 0;
e3c68b
+}
e3c68b
 
e3c68b
-    ret = *retval;
e3c68b
+int
e3c68b
+cs_update_xattrs(call_frame_t *frame, dict_t *xdata)
e3c68b
+{
e3c68b
+    cs_local_t *local = NULL;
e3c68b
+    xlator_t *this = NULL;
e3c68b
+    int size = -1;
e3c68b
+    GF_UNUSED int ret = 0;
e3c68b
+
e3c68b
+    local = frame->local;
e3c68b
+    this = frame->this;
e3c68b
+
e3c68b
+    local->xattrinfo.lxattr = GF_CALLOC(1, sizeof(cs_loc_xattr_t),
e3c68b
+                                        gf_cs_mt_cs_lxattr_t);
e3c68b
+    if (!local->xattrinfo.lxattr) {
e3c68b
+        local->op_ret = -1;
e3c68b
+        local->op_errno = ENOMEM;
e3c68b
+        goto err;
e3c68b
+    }
e3c68b
+
e3c68b
+    gf_uuid_copy(local->xattrinfo.lxattr->gfid, local->loc.gfid);
e3c68b
+
e3c68b
+    if (local->remotepath) {
e3c68b
+        local->xattrinfo.lxattr->file_path = gf_strdup(local->remotepath);
e3c68b
+        if (!local->xattrinfo.lxattr->file_path) {
e3c68b
+            local->op_ret = -1;
e3c68b
+            local->op_errno = ENOMEM;
e3c68b
+            goto err;
e3c68b
+        }
e3c68b
+    }
e3c68b
+
e3c68b
+    ret = dict_get_gfuuid(xdata, GF_CS_XATTR_ARCHIVE_UUID,
e3c68b
+                          &(local->xattrinfo.lxattr->uuid));
e3c68b
+
e3c68b
+    if (ret) {
e3c68b
+        gf_uuid_clear(local->xattrinfo.lxattr->uuid);
e3c68b
+    }
e3c68b
+    size = strlen(this->name) - strlen("-cloudsync") + 1;
e3c68b
+    local->xattrinfo.lxattr->volname = GF_CALLOC(1, size, gf_common_mt_char);
e3c68b
+    if (!local->xattrinfo.lxattr->volname) {
e3c68b
+        local->op_ret = -1;
e3c68b
+        local->op_errno = ENOMEM;
e3c68b
+        goto err;
e3c68b
+    }
e3c68b
+    strncpy(local->xattrinfo.lxattr->volname, this->name, size - 1);
e3c68b
+    local->xattrinfo.lxattr->volname[size - 1] = '\0';
e3c68b
+
e3c68b
+    return 0;
e3c68b
+err:
e3c68b
+    cs_xattrinfo_wipe(local);
e3c68b
+    return -1;
e3c68b
+}
e3c68b
+
e3c68b
+int
e3c68b
+cs_serve_readv(call_frame_t *frame, off_t offset, size_t size, uint32_t flags)
e3c68b
+{
e3c68b
+    xlator_t *this = NULL;
e3c68b
+    cs_private_t *priv = NULL;
e3c68b
+    int ret = -1;
e3c68b
+    fd_t *fd = NULL;
e3c68b
+    cs_local_t *local = NULL;
e3c68b
+
e3c68b
+    local = frame->local;
e3c68b
+    this = frame->this;
e3c68b
+    priv = this->private;
e3c68b
+
e3c68b
+    if (!local->remotepath) {
e3c68b
+        ret = -1;
e3c68b
+        gf_msg(this->name, GF_LOG_ERROR, 0, 0,
e3c68b
+               "remote path not"
e3c68b
+               " available. Check posix logs to resolve");
e3c68b
+        goto out;
e3c68b
+    }
e3c68b
+
e3c68b
+    if (!priv->stores) {
e3c68b
+        gf_msg(this->name, GF_LOG_ERROR, 0, 0,
e3c68b
+               "No remote store "
e3c68b
+               "plugins found");
e3c68b
+        ret = -1;
e3c68b
+        goto out;
e3c68b
+    }
e3c68b
+
e3c68b
+    if (local->fd) {
e3c68b
+        fd = fd_anonymous(local->fd->inode);
e3c68b
+    } else {
e3c68b
+        fd = fd_anonymous(local->loc.inode);
e3c68b
+    }
e3c68b
+
e3c68b
+    local->xattrinfo.size = size;
e3c68b
+    local->xattrinfo.offset = offset;
e3c68b
+    local->xattrinfo.flags = flags;
e3c68b
+
e3c68b
+    if (!fd) {
e3c68b
+        gf_msg("CS", GF_LOG_ERROR, 0, 0, "fd creation failed");
e3c68b
+        ret = -1;
e3c68b
+        goto out;
e3c68b
+    }
e3c68b
+
e3c68b
+    local->dlfd = fd;
e3c68b
+    local->dloffset = offset;
e3c68b
+
e3c68b
+    /*this calling method is for per volume setting */
e3c68b
+    ret = priv->stores->rdfop(frame, priv->stores->config);
e3c68b
+    if (ret) {
e3c68b
+        gf_msg(this->name, GF_LOG_ERROR, 0, 0,
e3c68b
+               "read failed"
e3c68b
+               ", remotepath: %s",
e3c68b
+               local->remotepath);
e3c68b
+        ret = -1;
e3c68b
+        goto out;
e3c68b
+    } else {
e3c68b
+        gf_msg(this->name, GF_LOG_INFO, 0, 0,
e3c68b
+               "read success, path"
e3c68b
+               " : %s",
e3c68b
+               local->remotepath);
e3c68b
+    }
e3c68b
 
e3c68b
 out:
e3c68b
-    if (retval)
e3c68b
-        GF_FREE(retval);
e3c68b
+    if (fd) {
e3c68b
+        fd_unref(fd);
e3c68b
+        local->dlfd = NULL;
e3c68b
+    }
e3c68b
+    return ret;
e3c68b
+}
e3c68b
+
e3c68b
+int32_t
e3c68b
+cs_readv_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret,
e3c68b
+             int32_t op_errno, struct iovec *vector, int32_t count,
e3c68b
+             struct iatt *stbuf, struct iobref *iobref, dict_t *xdata)
e3c68b
+{
e3c68b
+    cs_local_t *local = NULL;
e3c68b
+    int ret = 0;
e3c68b
+    uint64_t val = 0;
e3c68b
+    fd_t *fd = NULL;
e3c68b
+
e3c68b
+    local = frame->local;
e3c68b
+    fd = local->fd;
e3c68b
+
e3c68b
+    local->call_cnt++;
e3c68b
+
e3c68b
+    if (op_ret == -1) {
e3c68b
+        ret = dict_get_uint64(xdata, GF_CS_OBJECT_STATUS, &val;;
e3c68b
+        if (ret == 0) {
e3c68b
+            if (val == GF_CS_ERROR) {
e3c68b
+                gf_msg(this->name, GF_LOG_ERROR, 0, 0,
e3c68b
+                       "could not get file state, unwinding");
e3c68b
+                op_ret = -1;
e3c68b
+                op_errno = EIO;
e3c68b
+                goto unwind;
e3c68b
+            } else {
e3c68b
+                __cs_inode_ctx_update(this, fd->inode, val);
e3c68b
+                gf_msg(this->name, GF_LOG_INFO, 0, 0, " state = %" PRIu64, val);
e3c68b
+
e3c68b
+                if (local->call_cnt == 1 &&
e3c68b
+                    (val == GF_CS_REMOTE || val == GF_CS_DOWNLOADING)) {
e3c68b
+                    gf_msg(this->name, GF_LOG_INFO, 0, 0,
e3c68b
+                           " will read from remote : %" PRIu64, val);
e3c68b
+                    goto repair;
e3c68b
+                } else {
e3c68b
+                    gf_msg(this->name, GF_LOG_ERROR, 0, 0,
e3c68b
+                           "second readv, Unwinding");
e3c68b
+                    goto unwind;
e3c68b
+                }
e3c68b
+            }
e3c68b
+        } else {
e3c68b
+            gf_msg(this->name, GF_LOG_ERROR, 0, 0,
e3c68b
+                   "file state "
e3c68b
+                   "could not be figured, unwinding");
e3c68b
+            goto unwind;
e3c68b
+        }
e3c68b
+    } else {
e3c68b
+        /* successful readv => file is local */
e3c68b
+        __cs_inode_ctx_update(this, fd->inode, GF_CS_LOCAL);
e3c68b
+        gf_msg(this->name, GF_LOG_INFO, 0, 0,
e3c68b
+               "state : GF_CS_LOCAL"
e3c68b
+               ", readv successful");
e3c68b
+
e3c68b
+        goto unwind;
e3c68b
+    }
e3c68b
+
e3c68b
+repair:
e3c68b
+    ret = locate_and_execute(frame);
e3c68b
+    if (ret) {
e3c68b
+        goto unwind;
e3c68b
+    }
e3c68b
+
e3c68b
+    return 0;
e3c68b
+
e3c68b
+unwind:
e3c68b
+    CS_STACK_UNWIND(readv, frame, op_ret, op_errno, vector, count, stbuf,
e3c68b
+                    iobref, xdata);
e3c68b
+
e3c68b
+    return 0;
e3c68b
+}
e3c68b
+
e3c68b
+int32_t
e3c68b
+cs_resume_readv(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size,
e3c68b
+                off_t offset, uint32_t flags, dict_t *xdata)
e3c68b
+{
e3c68b
+    int ret = 0;
e3c68b
+
e3c68b
+    ret = cs_resume_postprocess(this, frame, fd->inode);
e3c68b
+    if (ret) {
e3c68b
+        goto unwind;
e3c68b
+    }
e3c68b
+
e3c68b
+    cs_inodelk_unlock(frame);
e3c68b
+
e3c68b
+    STACK_WIND(frame, cs_readv_cbk, FIRST_CHILD(this),
e3c68b
+               FIRST_CHILD(this)->fops->readv, fd, size, offset, flags, xdata);
e3c68b
+
e3c68b
+    return 0;
e3c68b
+
e3c68b
+unwind:
e3c68b
+    cs_inodelk_unlock(frame);
e3c68b
+
e3c68b
+    cs_common_cbk(frame);
e3c68b
+
e3c68b
+    return 0;
e3c68b
+}
e3c68b
+
e3c68b
+int32_t
e3c68b
+cs_resume_remote_readv(call_frame_t *frame, xlator_t *this, fd_t *fd,
e3c68b
+                       size_t size, off_t offset, uint32_t flags, dict_t *xdata)
e3c68b
+{
e3c68b
+    int ret = 0;
e3c68b
+    cs_local_t *local = NULL;
e3c68b
+    gf_cs_obj_state state = -1;
e3c68b
+    cs_inode_ctx_t *ctx = NULL;
e3c68b
+
e3c68b
+    cs_inodelk_unlock(frame);
e3c68b
+
e3c68b
+    local = frame->local;
e3c68b
+    if (!local) {
e3c68b
+        ret = -1;
e3c68b
+        goto unwind;
e3c68b
+    }
e3c68b
+
e3c68b
+    __cs_inode_ctx_get(this, fd->inode, &ctx;;
e3c68b
+
e3c68b
+    state = __cs_get_file_state(this, fd->inode, ctx);
e3c68b
+    if (state == GF_CS_ERROR) {
e3c68b
+        gf_msg(this->name, GF_LOG_ERROR, 0, 0,
e3c68b
+               "status is GF_CS_ERROR."
e3c68b
+               " Aborting readv");
e3c68b
+        local->op_ret = -1;
e3c68b
+        local->op_errno = EREMOTE;
e3c68b
+        ret = -1;
e3c68b
+        goto unwind;
e3c68b
+    }
e3c68b
+
e3c68b
+    /* Serve readv from remote store only if it is remote. */
e3c68b
+    gf_msg_debug(this->name, 0, "status of file %s is %d",
e3c68b
+                 local->remotepath ? local->remotepath : "", state);
e3c68b
+
e3c68b
+    /* We will reach this condition if local inode ctx had REMOTE
e3c68b
+     * state when the control was in cs_readv but after stat
e3c68b
+     * we got an updated state saying that the file is LOCAL.
e3c68b
+     */
e3c68b
+    if (state == GF_CS_LOCAL) {
e3c68b
+        STACK_WIND(frame, cs_readv_cbk, FIRST_CHILD(this),
e3c68b
+                   FIRST_CHILD(this)->fops->readv, fd, size, offset, flags,
e3c68b
+                   xdata);
e3c68b
+    } else if (state == GF_CS_REMOTE) {
e3c68b
+        ret = cs_resume_remote_readv_postprocess(this, frame, fd->inode, offset,
e3c68b
+                                                 size, flags);
e3c68b
+        /* Failed to submit the remote readv fop to plugin */
e3c68b
+        if (ret) {
e3c68b
+            local->op_ret = -1;
e3c68b
+            local->op_errno = EREMOTE;
e3c68b
+            goto unwind;
e3c68b
+        }
e3c68b
+        /* When the file is in any other intermediate state,
e3c68b
+         * we should not perform remote reads.
e3c68b
+         */
e3c68b
+    } else {
e3c68b
+        local->op_ret = -1;
e3c68b
+        local->op_errno = EINVAL;
e3c68b
+        goto unwind;
e3c68b
+    }
e3c68b
+
e3c68b
+    return 0;
e3c68b
+
e3c68b
+unwind:
e3c68b
+    cs_common_cbk(frame);
e3c68b
+
e3c68b
+    return 0;
e3c68b
+}
e3c68b
+
e3c68b
+int32_t
e3c68b
+cs_readv(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size,
e3c68b
+         off_t offset, uint32_t flags, dict_t *xdata)
e3c68b
+{
e3c68b
+    int op_errno = -1;
e3c68b
+    cs_local_t *local = NULL;
e3c68b
+    int ret = 0;
e3c68b
+    cs_inode_ctx_t *ctx = NULL;
e3c68b
+    gf_cs_obj_state state = -1;
e3c68b
+    cs_private_t *priv = NULL;
e3c68b
+
e3c68b
+    VALIDATE_OR_GOTO(frame, err);
e3c68b
+    VALIDATE_OR_GOTO(this, err);
e3c68b
+    VALIDATE_OR_GOTO(fd, err);
e3c68b
+
e3c68b
+    priv = this->private;
e3c68b
+
e3c68b
+    local = cs_local_init(this, frame, NULL, fd, GF_FOP_READ);
e3c68b
+    if (!local) {
e3c68b
+        gf_msg(this->name, GF_LOG_ERROR, 0, 0, "local init failed");
e3c68b
+        op_errno = ENOMEM;
e3c68b
+        goto err;
e3c68b
+    }
e3c68b
+
e3c68b
+    __cs_inode_ctx_get(this, fd->inode, &ctx;;
e3c68b
+
e3c68b
+    if (ctx)
e3c68b
+        state = __cs_get_file_state(this, fd->inode, ctx);
e3c68b
+    else
e3c68b
+        state = GF_CS_LOCAL;
e3c68b
+
e3c68b
+    local->xattr_req = xdata ? dict_ref(xdata) : (xdata = dict_new());
e3c68b
+
e3c68b
+    ret = dict_set_uint32(local->xattr_req, GF_CS_OBJECT_STATUS, 1);
e3c68b
+    if (ret) {
e3c68b
+        gf_msg(this->name, GF_LOG_ERROR, 0, 0,
e3c68b
+               "dict_set failed key:"
e3c68b
+               " %s",
e3c68b
+               GF_CS_OBJECT_STATUS);
e3c68b
+        goto err;
e3c68b
+    }
e3c68b
+
e3c68b
+    if (priv->remote_read) {
e3c68b
+        local->stub = fop_readv_stub(frame, cs_resume_remote_readv, fd, size,
e3c68b
+                                     offset, flags, xdata);
e3c68b
+    } else {
e3c68b
+        local->stub = fop_readv_stub(frame, cs_resume_readv, fd, size, offset,
e3c68b
+                                     flags, xdata);
e3c68b
+    }
e3c68b
+    if (!local->stub) {
e3c68b
+        gf_msg(this->name, GF_LOG_ERROR, 0, 0, "insufficient memory");
e3c68b
+        op_errno = ENOMEM;
e3c68b
+        goto err;
e3c68b
+    }
e3c68b
+
e3c68b
+    if (state == GF_CS_LOCAL) {
e3c68b
+        STACK_WIND(frame, cs_readv_cbk, FIRST_CHILD(this),
e3c68b
+                   FIRST_CHILD(this)->fops->readv, fd, size, offset, flags,
e3c68b
+                   xdata);
e3c68b
+    } else {
e3c68b
+        local->call_cnt++;
e3c68b
+        ret = locate_and_execute(frame);
e3c68b
+        if (ret) {
e3c68b
+            op_errno = ENOMEM;
e3c68b
+            goto err;
e3c68b
+        }
e3c68b
+    }
e3c68b
+
e3c68b
+    return 0;
e3c68b
+
e3c68b
+err:
e3c68b
+    CS_STACK_UNWIND(readv, frame, -1, op_errno, NULL, -1, NULL, NULL, NULL);
e3c68b
+
e3c68b
+    return 0;
e3c68b
+}
e3c68b
+
e3c68b
+int
e3c68b
+cs_resume_remote_readv_postprocess(xlator_t *this, call_frame_t *frame,
e3c68b
+                                   inode_t *inode, off_t offset, size_t size,
e3c68b
+                                   uint32_t flags)
e3c68b
+{
e3c68b
+    int ret = 0;
e3c68b
+
e3c68b
+    ret = cs_serve_readv(frame, offset, size, flags);
e3c68b
 
e3c68b
     return ret;
e3c68b
 }
e3c68b
@@ -1059,7 +1414,7 @@ cs_stat_check_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret,
e3c68b
                 goto err;
e3c68b
             } else {
e3c68b
                 ret = __cs_inode_ctx_update(this, inode, val);
e3c68b
-                gf_msg_debug(this->name, 0, "status : %lu", val);
e3c68b
+                gf_msg_debug(this->name, 0, "status : %" PRIu64, val);
e3c68b
                 if (ret) {
e3c68b
                     gf_msg(this->name, GF_LOG_ERROR, 0, 0, "ctx update failed");
e3c68b
                     local->op_ret = -1;
e3c68b
@@ -1087,6 +1442,10 @@ cs_stat_check_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret,
e3c68b
             gf_msg_debug(this->name, 0, "NULL filepath");
e3c68b
         }
e3c68b
 
e3c68b
+        ret = cs_update_xattrs(frame, xdata);
e3c68b
+        if (ret)
e3c68b
+            goto err;
e3c68b
+
e3c68b
         local->op_ret = 0;
e3c68b
         local->xattr_rsp = dict_ref(xdata);
e3c68b
         memcpy(&local->stbuf, stbuf, sizeof(struct iatt));
e3c68b
@@ -1121,6 +1480,8 @@ cs_do_stat_check(call_frame_t *main_frame)
e3c68b
         goto err;
e3c68b
     }
e3c68b
 
e3c68b
+    cs_set_xattr_req(main_frame);
e3c68b
+
e3c68b
     if (local->fd) {
e3c68b
         STACK_WIND(main_frame, cs_stat_check_cbk, FIRST_CHILD(this),
e3c68b
                    FIRST_CHILD(this)->fops->fstat, local->fd, local->xattr_req);
e3c68b
@@ -1177,6 +1538,10 @@ cs_common_cbk(call_frame_t *frame)
e3c68b
                             NULL, NULL, NULL);
e3c68b
             break;
e3c68b
 
e3c68b
+        case GF_FOP_TRUNCATE:
e3c68b
+            CS_STACK_UNWIND(truncate, frame, local->op_ret, local->op_errno,
e3c68b
+                            NULL, NULL, NULL);
e3c68b
+            break;
e3c68b
         default:
e3c68b
             break;
e3c68b
     }
e3c68b
@@ -1427,7 +1792,7 @@ __cs_inode_ctx_get(xlator_t *this, inode_t *inode, cs_inode_ctx_t **ctx)
e3c68b
     if (ret)
e3c68b
         *ctx = NULL;
e3c68b
     else
e3c68b
-        *ctx = (cs_inode_ctx_t *)ctxint;
e3c68b
+        *ctx = (cs_inode_ctx_t *)(uintptr_t)ctxint;
e3c68b
 
e3c68b
     return;
e3c68b
 }
e3c68b
@@ -1452,7 +1817,7 @@ __cs_inode_ctx_update(xlator_t *this, inode_t *inode, uint64_t val)
e3c68b
 
e3c68b
             ctx->state = val;
e3c68b
 
e3c68b
-            ctxint = (uint64_t)ctx;
e3c68b
+            ctxint = (uint64_t)(uintptr_t)ctx;
e3c68b
 
e3c68b
             ret = __inode_ctx_set(inode, this, &ctxint);
e3c68b
             if (ret) {
e3c68b
@@ -1460,7 +1825,7 @@ __cs_inode_ctx_update(xlator_t *this, inode_t *inode, uint64_t val)
e3c68b
                 goto out;
e3c68b
             }
e3c68b
         } else {
e3c68b
-            ctx = (cs_inode_ctx_t *)ctxint;
e3c68b
+            ctx = (cs_inode_ctx_t *)(uintptr_t)ctxint;
e3c68b
 
e3c68b
             ctx->state = val;
e3c68b
         }
e3c68b
@@ -1483,7 +1848,7 @@ cs_inode_ctx_reset(xlator_t *this, inode_t *inode)
e3c68b
         return 0;
e3c68b
     }
e3c68b
 
e3c68b
-    ctx = (cs_inode_ctx_t *)ctxint;
e3c68b
+    ctx = (cs_inode_ctx_t *)(uintptr_t)ctxint;
e3c68b
 
e3c68b
     GF_FREE(ctx);
e3c68b
     return 0;
e3c68b
@@ -1532,6 +1897,57 @@ cs_resume_postprocess(xlator_t *this, call_frame_t *frame, inode_t *inode)
e3c68b
 out:
e3c68b
     return ret;
e3c68b
 }
e3c68b
+
e3c68b
+int32_t
e3c68b
+__cs_get_dict_str(char **str, dict_t *xattr, const char *name, int *errnum)
e3c68b
+{
e3c68b
+    data_t *data = NULL;
e3c68b
+    int ret = -1;
e3c68b
+
e3c68b
+    assert(str != NULL);
e3c68b
+
e3c68b
+    data = dict_get(xattr, (char *)name);
e3c68b
+    if (!data) {
e3c68b
+        *errnum = ENODATA;
e3c68b
+        goto out;
e3c68b
+    }
e3c68b
+
e3c68b
+    *str = GF_CALLOC(data->len + 1, sizeof(char), gf_common_mt_char);
e3c68b
+    if (!(*str)) {
e3c68b
+        *errnum = ENOMEM;
e3c68b
+        goto out;
e3c68b
+    }
e3c68b
+
e3c68b
+    memcpy(*str, data->data, sizeof(char) * (data->len));
e3c68b
+    return 0;
e3c68b
+
e3c68b
+out:
e3c68b
+    return ret;
e3c68b
+}
e3c68b
+
e3c68b
+int32_t
e3c68b
+__cs_get_dict_uuid(uuid_t uuid, dict_t *xattr, const char *name, int *errnum)
e3c68b
+{
e3c68b
+    data_t *data = NULL;
e3c68b
+    int ret = -1;
e3c68b
+
e3c68b
+    assert(uuid != NULL);
e3c68b
+
e3c68b
+    data = dict_get(xattr, (char *)name);
e3c68b
+    if (!data) {
e3c68b
+        *errnum = ENODATA;
e3c68b
+        goto out;
e3c68b
+    }
e3c68b
+
e3c68b
+    assert(data->len == sizeof(uuid_t));
e3c68b
+
e3c68b
+    gf_uuid_copy(uuid, (unsigned char *)data->data);
e3c68b
+    return 0;
e3c68b
+
e3c68b
+out:
e3c68b
+    return ret;
e3c68b
+}
e3c68b
+
e3c68b
 int32_t
e3c68b
 cs_fdctx_to_dict(xlator_t *this, fd_t *fd, dict_t *dict)
e3c68b
 {
e3c68b
@@ -1606,7 +2022,6 @@ cs_notify(xlator_t *this, int event, void *data, ...)
e3c68b
 
e3c68b
 struct xlator_fops cs_fops = {
e3c68b
     .stat = cs_stat,
e3c68b
-    .readdirp = cs_readdirp,
e3c68b
     .truncate = cs_truncate,
e3c68b
     .seek = cs_seek,
e3c68b
     .statfs = cs_statfs,
e3c68b
@@ -1627,7 +2042,9 @@ struct xlator_fops cs_fops = {
e3c68b
     .zerofill = cs_zerofill,
e3c68b
 };
e3c68b
 
e3c68b
-struct xlator_cbks cs_cbks = {};
e3c68b
+struct xlator_cbks cs_cbks = {
e3c68b
+    .forget = cs_forget,
e3c68b
+};
e3c68b
 
e3c68b
 struct xlator_dumpops cs_dumpops = {
e3c68b
     .fdctx_to_dict = cs_fdctx_to_dict,
e3c68b
@@ -1647,6 +2064,15 @@ struct volume_options cs_options[] = {
e3c68b
     {.key = {"cloudsync-storetype"},
e3c68b
      .type = GF_OPTION_TYPE_STR,
e3c68b
      .description = "Defines which remote store is enabled"},
e3c68b
+    {.key = {"cloudsync-remote-read"},
e3c68b
+     .type = GF_OPTION_TYPE_BOOL,
e3c68b
+     .description = "Defines a remote read fop when on"},
e3c68b
+    {.key = {"cloudsync-store-id"},
e3c68b
+     .type = GF_OPTION_TYPE_STR,
e3c68b
+     .description = "Defines a volume wide store id"},
e3c68b
+    {.key = {"cloudsync-product-id"},
e3c68b
+     .type = GF_OPTION_TYPE_STR,
e3c68b
+     .description = "Defines a volume wide product id"},
e3c68b
     {.key = {NULL}},
e3c68b
 };
e3c68b
 
e3c68b
diff --git a/xlators/features/cloudsync/src/cloudsync.h b/xlators/features/cloudsync/src/cloudsync.h
e3c68b
index dbdb207..0cb800a 100644
e3c68b
--- a/xlators/features/cloudsync/src/cloudsync.h
e3c68b
+++ b/xlators/features/cloudsync/src/cloudsync.h
e3c68b
@@ -19,6 +19,7 @@
e3c68b
 #include "cloudsync-common.h"
e3c68b
 #include "cloudsync-autogen-fops.h"
e3c68b
 
e3c68b
+#define ALIGN_SIZE 4096
e3c68b
 #define CS_LOCK_DOMAIN "cs.protect.file.stat"
e3c68b
 typedef struct cs_dlstore {
e3c68b
     off_t off;
e3c68b
@@ -29,6 +30,7 @@ typedef struct cs_dlstore {
e3c68b
 } cs_dlstore;
e3c68b
 
e3c68b
 typedef struct cs_inode_ctx {
e3c68b
+    cs_loc_xattr_t locxattr;
e3c68b
     gf_cs_obj_state state;
e3c68b
 } cs_inode_ctx_t;
e3c68b
 
e3c68b
@@ -100,4 +102,22 @@ cs_truncate_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
e3c68b
 int32_t
e3c68b
 cs_resume_truncate(call_frame_t *frame, xlator_t *this, loc_t *loc,
e3c68b
                    off_t offset, dict_t *xattr_req);
e3c68b
+
e3c68b
+int32_t
e3c68b
+cs_readv_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret,
e3c68b
+             int32_t op_errno, struct iovec *vector, int32_t count,
e3c68b
+             struct iatt *stbuf, struct iobref *iobref, dict_t *xdata);
e3c68b
+int32_t
e3c68b
+cs_resume_readv(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size,
e3c68b
+                off_t offset, uint32_t flags, dict_t *xdata);
e3c68b
+int32_t
e3c68b
+cs_readv(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size,
e3c68b
+         off_t offset, uint32_t flags, dict_t *xdata);
e3c68b
+
e3c68b
+int
e3c68b
+cs_resume_remote_readv_postprocess(xlator_t *this, call_frame_t *frame,
e3c68b
+                                   inode_t *inode, off_t offset, size_t size,
e3c68b
+                                   uint32_t flags);
e3c68b
+int
e3c68b
+cs_serve_readv(call_frame_t *frame, off_t offset, size_t size, uint32_t flags);
e3c68b
 #endif /* __CLOUDSYNC_H__ */
e3c68b
diff --git a/xlators/mgmt/glusterd/src/glusterd-volume-set.c b/xlators/mgmt/glusterd/src/glusterd-volume-set.c
e3c68b
index 4b32fb6..73abf37 100644
e3c68b
--- a/xlators/mgmt/glusterd/src/glusterd-volume-set.c
e3c68b
+++ b/xlators/mgmt/glusterd/src/glusterd-volume-set.c
e3c68b
@@ -3693,7 +3693,7 @@ struct volopt_map_entry glusterd_volopt_map[] = {
e3c68b
      .op_version = GD_OP_VERSION_5_0,
e3c68b
      .description = "enable/disable noatime option with ctime enabled.",
e3c68b
      .flags = VOLOPT_FLAG_CLIENT_OPT | VOLOPT_FLAG_XLATOR_OPT},
e3c68b
-    {.key = "feature.cloudsync-storetype",
e3c68b
+    {.key = "features.cloudsync-storetype",
e3c68b
      .voltype = "features/cloudsync",
e3c68b
      .op_version = GD_OP_VERSION_5_0,
e3c68b
      .flags = VOLOPT_FLAG_CLIENT_OPT},
e3c68b
@@ -3721,4 +3721,9 @@ struct volopt_map_entry glusterd_volopt_map[] = {
e3c68b
      .validate_fn = validate_boolean,
e3c68b
      .description = "option to enforce mandatory lock on a file",
e3c68b
      .flags = VOLOPT_FLAG_XLATOR_OPT},
e3c68b
+    {.key = "features.cloudsync-remote-read",
e3c68b
+     .voltype = "features/cloudsync",
e3c68b
+     .value = "off",
e3c68b
+     .op_version = GD_OP_VERSION_6_0,
e3c68b
+     .flags = VOLOPT_FLAG_CLIENT_OPT},
e3c68b
     {.key = NULL}};
e3c68b
-- 
e3c68b
1.8.3.1
e3c68b