e3c68b
From b402b89f71a3ebabca24c459f106af1f9610939a Mon Sep 17 00:00:00 2001
e3c68b
From: Anuradha Talur <atalur@commvault.com>
e3c68b
Date: Fri, 30 Nov 2018 11:23:07 -0800
e3c68b
Subject: [PATCH 154/169] cloudsync/cvlt: Cloudsync plugin for commvault store
e3c68b
e3c68b
backport of: https://review.gluster.org/#/c/glusterfs/+/21771/
e3c68b
e3c68b
> Change-Id: Icbe53e78e9c4f6699c7a26a806ef4b14b39f5019
e3c68b
> updates: bz#1642168
e3c68b
> Signed-off-by: Anuradha Talur <atalur@commvault.com>
e3c68b
e3c68b
Change-Id: Ib543605daa51fa1cfe77ed475390a30ef14e6452
e3c68b
Signed-off-by: Susant Palai <spalai@redhat.com>
e3c68b
Reviewed-on: https://code.engineering.redhat.com/gerrit/172194
e3c68b
Tested-by: RHGS Build Bot <nigelb@redhat.com>
e3c68b
Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
e3c68b
---
e3c68b
 configure.ac                                       |  13 +
e3c68b
 glusterfs.spec.in                                  |   1 +
e3c68b
 libglusterfs/src/glusterfs/glfs-message-id.h       |   1 +
e3c68b
 .../src/cloudsync-plugins/src/Makefile.am          |   6 +-
e3c68b
 .../src/cloudsync-plugins/src/cvlt/Makefile.am     |   3 +
e3c68b
 .../src/cloudsync-plugins/src/cvlt/src/Makefile.am |  12 +
e3c68b
 .../cloudsync-plugins/src/cvlt/src/archivestore.h  | 203 +++++
e3c68b
 .../cloudsync-plugins/src/cvlt/src/cvlt-messages.h |  30 +
e3c68b
 .../src/cvlt/src/libcloudsynccvlt.sym              |   1 +
e3c68b
 .../src/cvlt/src/libcvlt-mem-types.h               |  19 +
e3c68b
 .../src/cloudsync-plugins/src/cvlt/src/libcvlt.c   | 842 +++++++++++++++++++++
e3c68b
 .../src/cloudsync-plugins/src/cvlt/src/libcvlt.h   |  84 ++
e3c68b
 xlators/features/cloudsync/src/cloudsync.c         |   6 +-
e3c68b
 xlators/mgmt/glusterd/src/glusterd-volume-set.c    |  10 +-
e3c68b
 14 files changed, 1228 insertions(+), 3 deletions(-)
e3c68b
 create mode 100644 xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/Makefile.am
e3c68b
 create mode 100644 xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/Makefile.am
e3c68b
 create mode 100644 xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/archivestore.h
e3c68b
 create mode 100644 xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/cvlt-messages.h
e3c68b
 create mode 100644 xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/libcloudsynccvlt.sym
e3c68b
 create mode 100644 xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/libcvlt-mem-types.h
e3c68b
 create mode 100644 xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/libcvlt.c
e3c68b
 create mode 100644 xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/libcvlt.h
e3c68b
e3c68b
diff --git a/configure.ac b/configure.ac
e3c68b
index 0e11d4c..f597b86 100644
e3c68b
--- a/configure.ac
e3c68b
+++ b/configure.ac
e3c68b
@@ -170,6 +170,8 @@ AC_CONFIG_FILES([Makefile
e3c68b
                 xlators/features/cloudsync/src/cloudsync-plugins/src/Makefile
e3c68b
                 xlators/features/cloudsync/src/cloudsync-plugins/src/cloudsyncs3/Makefile
e3c68b
                 xlators/features/cloudsync/src/cloudsync-plugins/src/cloudsyncs3/src/Makefile
e3c68b
+                xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/Makefile
e3c68b
+                xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/Makefile
e3c68b
                 xlators/playground/Makefile
e3c68b
                 xlators/playground/template/Makefile
e3c68b
                 xlators/playground/template/src/Makefile
e3c68b
@@ -937,6 +939,17 @@ AM_CONDITIONAL([BUILD_AMAZONS3_PLUGIN], [test "x$HAVE_AMAZONS3" = "xyes"])
e3c68b
 if test "x$HAVE_AMAZONS3" = "xyes";then
e3c68b
    BUILD_CLOUDSYNC="yes"
e3c68b
 fi
e3c68b
+BUILD_CVLT_PLUGIN="no"
e3c68b
+case $host_os in
e3c68b
+#enable cvlt plugin only for linux platforms
e3c68b
+     linux*)
e3c68b
+       BUILD_CVLT_PLUGIN="yes"
e3c68b
+       BUILD_CLOUDSYNC="yes"
e3c68b
+       ;;
e3c68b
+     *)
e3c68b
+       ;;
e3c68b
+esac
e3c68b
+AM_CONDITIONAL([BUILD_CVLT_PLUGIN], [test "x$BUILD_CVLT_PLUGIN" = "xyes"])
e3c68b
 AM_CONDITIONAL([BUILD_CLOUDSYNC], [test "x$BUILD_CLOUDSYNC" = "xyes"])
e3c68b
 dnl end cloudsync section
e3c68b
 
e3c68b
diff --git a/glusterfs.spec.in b/glusterfs.spec.in
e3c68b
index ed58356..85e75f2 100644
e3c68b
--- a/glusterfs.spec.in
e3c68b
+++ b/glusterfs.spec.in
e3c68b
@@ -1199,6 +1199,7 @@ exit 0
e3c68b
 %files cloudsync-plugins
e3c68b
 %dir %{_libdir}/glusterfs/%{version}%{?prereltag}/cloudsync-plugins
e3c68b
      %{_libdir}/glusterfs/%{version}%{?prereltag}/cloudsync-plugins/cloudsyncs3.so
e3c68b
+     %{_libdir}/glusterfs/%{version}%{?prereltag}/cloudsync-plugins/cloudsynccvlt.so
e3c68b
 
e3c68b
 %files devel
e3c68b
 %dir %{_includedir}/glusterfs
e3c68b
diff --git a/libglusterfs/src/glusterfs/glfs-message-id.h b/libglusterfs/src/glusterfs/glfs-message-id.h
e3c68b
index 001f4ab..a1a16ca 100644
e3c68b
--- a/libglusterfs/src/glusterfs/glfs-message-id.h
e3c68b
+++ b/libglusterfs/src/glusterfs/glfs-message-id.h
e3c68b
@@ -93,6 +93,7 @@ enum _msgid_comp {
e3c68b
     GLFS_MSGID_COMP(TEMPLATE, 1),
e3c68b
     GLFS_MSGID_COMP(UTIME, 1),
e3c68b
     GLFS_MSGID_COMP(SNAPVIEW_SERVER, 1),
e3c68b
+    GLFS_MSGID_COMP(CVLT, 1),
e3c68b
     /* --- new segments for messages goes above this line --- */
e3c68b
 
e3c68b
     GLFS_MSGID_END
e3c68b
diff --git a/xlators/features/cloudsync/src/cloudsync-plugins/src/Makefile.am b/xlators/features/cloudsync/src/cloudsync-plugins/src/Makefile.am
e3c68b
index 4deefb6..fb6b058 100644
e3c68b
--- a/xlators/features/cloudsync/src/cloudsync-plugins/src/Makefile.am
e3c68b
+++ b/xlators/features/cloudsync/src/cloudsync-plugins/src/Makefile.am
e3c68b
@@ -2,6 +2,10 @@ if BUILD_AMAZONS3_PLUGIN
e3c68b
   AMAZONS3_DIR = cloudsyncs3
e3c68b
 endif
e3c68b
 
e3c68b
-SUBDIRS = ${AMAZONS3_DIR}
e3c68b
+if BUILD_CVLT_PLUGIN
e3c68b
+  CVLT_DIR = cvlt
e3c68b
+endif
e3c68b
+
e3c68b
+SUBDIRS = ${AMAZONS3_DIR} ${CVLT_DIR}
e3c68b
 
e3c68b
 CLEANFILES =
e3c68b
diff --git a/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/Makefile.am b/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/Makefile.am
e3c68b
new file mode 100644
e3c68b
index 0000000..a985f42
e3c68b
--- /dev/null
e3c68b
+++ b/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/Makefile.am
e3c68b
@@ -0,0 +1,3 @@
e3c68b
+SUBDIRS = src
e3c68b
+
e3c68b
+CLEANFILES =
e3c68b
diff --git a/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/Makefile.am b/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/Makefile.am
e3c68b
new file mode 100644
e3c68b
index 0000000..b512464
e3c68b
--- /dev/null
e3c68b
+++ b/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/Makefile.am
e3c68b
@@ -0,0 +1,12 @@
e3c68b
+csp_LTLIBRARIES = cloudsynccvlt.la
e3c68b
+cspdir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/cloudsync-plugins
e3c68b
+
e3c68b
+cloudsynccvlt_la_SOURCES = libcvlt.c  $(top_srcdir)/xlators/features/cloudsync/src/cloudsync-common.c
e3c68b
+cloudsynccvlt_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la
e3c68b
+cloudsynccvlt_la_LDFLAGS = -module -avoid-version -export-symbols $(top_srcdir)/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/libcloudsynccvlt.sym
e3c68b
+AM_CPPFLAGS = $(GF_CPPFLAGS) -I$(top_srcdir)/libglusterfs/src   -I$(top_srcdir)/rpc/xdr/src -I$(top_builddir)/rpc/xdr/src
e3c68b
+noinst_HEADERS = archivestore.h libcvlt.h libcvlt-mem-types.h cvlt-messages.h
e3c68b
+AM_CFLAGS = -Wall -fno-strict-aliasing $(GF_CFLAGS) -I$(top_srcdir)/xlators/features/cloudsync/src
e3c68b
+CLEANFILES =
e3c68b
+
e3c68b
+EXTRA_DIST = libcloudsynccvlt.sym
e3c68b
diff --git a/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/archivestore.h b/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/archivestore.h
e3c68b
new file mode 100644
e3c68b
index 0000000..7230ef7
e3c68b
--- /dev/null
e3c68b
+++ b/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/archivestore.h
e3c68b
@@ -0,0 +1,203 @@
e3c68b
+/*
e3c68b
+  Copyright (c) 2018 Commvault Systems, Inc. <http://www.commvault.com>
e3c68b
+  This file is part of GlusterFS.
e3c68b
+
e3c68b
+  This file is licensed to you under your choice of the GNU Lesser
e3c68b
+  General Public License, version 3 or any later version (LGPLv3 or
e3c68b
+  later), or the GNU General Public License, version 2 (GPLv2), in all
e3c68b
+  cases as published by the Free Software Foundation.
e3c68b
+*/
e3c68b
+
e3c68b
+#ifndef __ARCHIVESTORE_H__
e3c68b
+#define __ARCHIVESTORE_H__
e3c68b
+
e3c68b
+#include <stdlib.h>
e3c68b
+#include <stddef.h>
e3c68b
+#include <stdint.h>
e3c68b
+#include <dlfcn.h>
e3c68b
+#include <uuid/uuid.h>
e3c68b
+
e3c68b
+#define CS_XATTR_ARCHIVE_UUID "trusted.cloudsync.uuid"
e3c68b
+#define CS_XATTR_PRODUCT_ID "trusted.cloudsync.product-id"
e3c68b
+#define CS_XATTR_STORE_ID "trusted.cloudsync.store-id"
e3c68b
+
e3c68b
+struct _archstore_methods;
e3c68b
+typedef struct _archstore_methods archstore_methods_t;
e3c68b
+
e3c68b
+struct _archstore_desc {
e3c68b
+    void *priv; /* Private field for store mgmt.   */
e3c68b
+                /* To be used only by archive store*/
e3c68b
+};
e3c68b
+typedef struct _archstore_desc archstore_desc_t;
e3c68b
+
e3c68b
+struct _archstore_info {
e3c68b
+    char *id;         /* Identifier for the archivestore */
e3c68b
+    uint32_t idlen;   /* Length of identifier string     */
e3c68b
+    char *prod;       /* Name of the data mgmt. product  */
e3c68b
+    uint32_t prodlen; /* Length of the product string    */
e3c68b
+};
e3c68b
+typedef struct _archstore_info archstore_info_t;
e3c68b
+
e3c68b
+struct _archstore_fileinfo {
e3c68b
+    uuid_t uuid;         /* uuid of the file                */
e3c68b
+    char *path;          /* file path                       */
e3c68b
+    uint32_t pathlength; /* length of file path             */
e3c68b
+};
e3c68b
+typedef struct _archstore_fileinfo archstore_fileinfo_t;
e3c68b
+
e3c68b
+struct _app_callback_info {
e3c68b
+    archstore_info_t *src_archstore;
e3c68b
+    archstore_fileinfo_t *src_archfile;
e3c68b
+    archstore_info_t *dest_archstore;
e3c68b
+    archstore_fileinfo_t *dest_archfile;
e3c68b
+};
e3c68b
+typedef struct _app_callback_info app_callback_info_t;
e3c68b
+
e3c68b
+typedef void (*app_callback_t)(archstore_desc_t *, app_callback_info_t *,
e3c68b
+                               void *, int64_t, int32_t);
e3c68b
+
e3c68b
+enum _archstore_scan_type { FULL = 1, INCREMENTAL = 2 };
e3c68b
+typedef enum _archstore_scan_type archstore_scan_type_t;
e3c68b
+
e3c68b
+typedef int32_t archstore_errno_t;
e3c68b
+
e3c68b
+/*
e3c68b
+ * Initialize archive store.
e3c68b
+ * arg1  pointer to structure containing archive store information
e3c68b
+ * arg2  error number if any generated during the initialization
e3c68b
+ * arg3  name of the log file
e3c68b
+ */
e3c68b
+typedef int32_t (*init_archstore_t)(archstore_desc_t *, archstore_errno_t *,
e3c68b
+                                    const char *);
e3c68b
+
e3c68b
+/*
e3c68b
+ * Clean up archive store.
e3c68b
+ * arg1  pointer to structure containing archive store information
e3c68b
+ * arg2  error number if any generated during the cleanup
e3c68b
+ */
e3c68b
+typedef int32_t (*term_archstore_t)(archstore_desc_t *, archstore_errno_t *);
e3c68b
+
e3c68b
+/*
e3c68b
+ * Read the contents of the file from archive store
e3c68b
+ * arg1  pointer to structure containing archive store description
e3c68b
+ * arg2  pointer to structure containing archive store information
e3c68b
+ * arg3  pointer to structure containing information about file to be read
e3c68b
+ * arg4  offset in the file from which data should be read
e3c68b
+ * arg5  buffer where the data should be read
e3c68b
+ * arg6  number of bytes of data to be read
e3c68b
+ * arg7  error number if any generated during the read from file
e3c68b
+ * arg8  callback handler to be invoked after the data is read
e3c68b
+ * arg9  cookie to be passed when callback is invoked
e3c68b
+ */
e3c68b
+typedef int32_t (*read_archstore_t)(archstore_desc_t *, archstore_info_t *,
e3c68b
+                                    archstore_fileinfo_t *, off_t, char *,
e3c68b
+                                    size_t, archstore_errno_t *, app_callback_t,
e3c68b
+                                    void *);
e3c68b
+
e3c68b
+/*
e3c68b
+ * Restore the contents of the file from archive store
e3c68b
+ * This is basically in-place restore
e3c68b
+ * arg1  pointer to structure containing archive store description
e3c68b
+ * arg2  pointer to structure containing archive store information
e3c68b
+ * arg3  pointer to structure containing information about file to be restored
e3c68b
+ * arg4  error number if any generated during the file restore
e3c68b
+ * arg5  callback to be invoked after the file is restored
e3c68b
+ * arg6  cookie to be passed when callback is invoked
e3c68b
+ */
e3c68b
+typedef int32_t (*recall_archstore_t)(archstore_desc_t *, archstore_info_t *,
e3c68b
+                                      archstore_fileinfo_t *,
e3c68b
+                                      archstore_errno_t *, app_callback_t,
e3c68b
+                                      void *);
e3c68b
+
e3c68b
+/*
e3c68b
+ * Restore the contents of the file from archive store to a different store
e3c68b
+ * This is basically out-of-place restore
e3c68b
+ * arg1  pointer to structure containing archive store description
e3c68b
+ * arg2  pointer to structure containing source archive store information
e3c68b
+ * arg3  pointer to structure containing information about file to be restored
e3c68b
+ * arg4  pointer to structure containing destination archive store information
e3c68b
+ * arg5  pointer to structure containing information about the location to
e3c68b
+         which the file will be restored
e3c68b
+ * arg6  error number if any generated during the file restore
e3c68b
+ * arg7  callback to be invoked after the file is restored
e3c68b
+ * arg8  cookie to be passed when callback is invoked
e3c68b
+ */
e3c68b
+typedef int32_t (*restore_archstore_t)(archstore_desc_t *, archstore_info_t *,
e3c68b
+                                       archstore_fileinfo_t *,
e3c68b
+                                       archstore_info_t *,
e3c68b
+                                       archstore_fileinfo_t *,
e3c68b
+                                       archstore_errno_t *, app_callback_t,
e3c68b
+                                       void *);
e3c68b
+
e3c68b
+/*
e3c68b
+ * Archive the contents of the file to archive store
e3c68b
+ * arg1  pointer to structure containing archive store description
e3c68b
+ * arg2  pointer to structure containing source archive store information
e3c68b
+ * arg3  pointer to structure containing information about files to be archived
e3c68b
+ * arg4  pointer to structure containing destination archive store information
e3c68b
+ * arg5  pointer to structure containing information about files that failed
e3c68b
+ *       to be archived
e3c68b
+ * arg6  error number if any generated during the file archival
e3c68b
+ * arg7  callback to be invoked after the file is archived
e3c68b
+ * arg8  cookie to be passed when callback is invoked
e3c68b
+ */
e3c68b
+typedef int32_t (*archive_archstore_t)(archstore_desc_t *, archstore_info_t *,
e3c68b
+                                       archstore_fileinfo_t *,
e3c68b
+                                       archstore_info_t *,
e3c68b
+                                       archstore_fileinfo_t *,
e3c68b
+                                       archstore_errno_t *, app_callback_t,
e3c68b
+                                       void *);
e3c68b
+
e3c68b
+/*
e3c68b
+ * Backup list of files provided in the input file
e3c68b
+ * arg1  pointer to structure containing archive store description
e3c68b
+ * arg2  pointer to structure containing source archive store information
e3c68b
+ * arg3  pointer to structure containing information about files to be backed up
e3c68b
+ * arg4  pointer to structure containing destination archive store information
e3c68b
+ * arg5  pointer to structure containing information about files that failed
e3c68b
+ *       to be backed up
e3c68b
+ * arg6  error number if any generated during the file archival
e3c68b
+ * arg7  callback to be invoked after the file is archived
e3c68b
+ * arg8  cookie to be passed when callback is invoked
e3c68b
+ */
e3c68b
+typedef int32_t (*backup_archstore_t)(archstore_desc_t *, archstore_info_t *,
e3c68b
+                                      archstore_fileinfo_t *,
e3c68b
+                                      archstore_info_t *,
e3c68b
+                                      archstore_fileinfo_t *,
e3c68b
+                                      archstore_errno_t *, app_callback_t,
e3c68b
+                                      void *);
e3c68b
+
e3c68b
+/*
e3c68b
+ * Scan the contents of a store and determine the files which need to be
e3c68b
+ * backed up.
e3c68b
+ * arg1  pointer to structure containing archive store description
e3c68b
+ * arg2  pointer to structure containing archive store information
e3c68b
+ * arg3  type of scan whether full or incremental
e3c68b
+ * arg4  path to file that contains list of files to be backed up
e3c68b
+ * arg5  error number if any generated during scan operation
e3c68b
+ */
e3c68b
+typedef int32_t (*scan_archstore_t)(archstore_desc_t *, archstore_info_t *,
e3c68b
+                                    archstore_scan_type_t, char *,
e3c68b
+                                    archstore_errno_t *);
e3c68b
+
e3c68b
+struct _archstore_methods {
e3c68b
+    init_archstore_t init;
e3c68b
+    term_archstore_t fini;
e3c68b
+    backup_archstore_t backup;
e3c68b
+    archive_archstore_t archive;
e3c68b
+    scan_archstore_t scan;
e3c68b
+    restore_archstore_t restore;
e3c68b
+    recall_archstore_t recall;
e3c68b
+    read_archstore_t read;
e3c68b
+};
e3c68b
+
e3c68b
+typedef int (*get_archstore_methods_t)(archstore_methods_t *);
e3c68b
+
e3c68b
+/*
e3c68b
+ * Single function that will be invoked by applications for extracting
e3c68b
+ * the function pointers to all data management functions.
e3c68b
+ */
e3c68b
+int32_t
e3c68b
+get_archstore_methods(archstore_methods_t *);
e3c68b
+
e3c68b
+#endif /* End of __ARCHIVESTORE_H__ */
e3c68b
diff --git a/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/cvlt-messages.h b/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/cvlt-messages.h
e3c68b
new file mode 100644
e3c68b
index 0000000..57c9aa7
e3c68b
--- /dev/null
e3c68b
+++ b/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/cvlt-messages.h
e3c68b
@@ -0,0 +1,30 @@
e3c68b
+/*
e3c68b
+ Copyright (c) 2015 Red Hat, Inc. <http://www.redhat.com>
e3c68b
+ This file is part of GlusterFS.
e3c68b
+
e3c68b
+ This file is licensed to you under your choice of the GNU Lesser
e3c68b
+ General Public License, version 3 or any later version (LGPLv3 or
e3c68b
+ later), or the GNU General Public License, version 2 (GPLv2), in all
e3c68b
+ cases as published by the Free Software Foundation.
e3c68b
+ */
e3c68b
+
e3c68b
+#ifndef _CVLT_MESSAGES_H_
e3c68b
+#define _CVLT_MESSAGES_H_
e3c68b
+
e3c68b
+#include <glusterfs/glfs-message-id.h>
e3c68b
+
e3c68b
+/* To add new message IDs, append new identifiers at the end of the list.
e3c68b
+ *
e3c68b
+ * Never remove a message ID. If it's not used anymore, you can rename it or
e3c68b
+ * leave it as it is, but not delete it. This is to prevent reutilization of
e3c68b
+ * IDs by other messages.
e3c68b
+ *
e3c68b
+ * The component name must match one of the entries defined in
e3c68b
+ * glfs-message-id.h.
e3c68b
+ */
e3c68b
+
e3c68b
+GLFS_MSGID(CVLT, CVLT_EXTRACTION_FAILED, CVLT_FREE,
e3c68b
+           CVLT_RESOURCE_ALLOCATION_FAILED, CVLT_RESTORE_FAILED,
e3c68b
+           CVLT_READ_FAILED, CVLT_NO_MEMORY, CVLT_DLOPEN_FAILED);
e3c68b
+
e3c68b
+#endif /* !_CVLT_MESSAGES_H_ */
e3c68b
diff --git a/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/libcloudsynccvlt.sym b/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/libcloudsynccvlt.sym
e3c68b
new file mode 100644
e3c68b
index 0000000..0bc2736
e3c68b
--- /dev/null
e3c68b
+++ b/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/libcloudsynccvlt.sym
e3c68b
@@ -0,0 +1 @@
e3c68b
+store_ops
e3c68b
diff --git a/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/libcvlt-mem-types.h b/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/libcvlt-mem-types.h
e3c68b
new file mode 100644
e3c68b
index 0000000..c24fab8
e3c68b
--- /dev/null
e3c68b
+++ b/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/libcvlt-mem-types.h
e3c68b
@@ -0,0 +1,19 @@
e3c68b
+/*
e3c68b
+ *   Copyright (c) 2018 Commvault Systems, Inc. <http://www.commvault.com>
e3c68b
+ *   This file is part of GlusterFS.
e3c68b
+ *
e3c68b
+ *   This file is licensed to you under your choice of the GNU Lesser
e3c68b
+ *   General Public License, version 3 or any later version (LGPLv3 or
e3c68b
+ *   later), or the GNU General Public License, version 2 (GPLv2), in all
e3c68b
+ *   cases as published by the Free Software Foundation.
e3c68b
+ */
e3c68b
+
e3c68b
+#ifndef __LIBCVLT_MEM_TYPES_H__
e3c68b
+#define __LIBCVLT_MEM_TYPES_H__
e3c68b
+
e3c68b
+#include <glusterfs/mem-types.h>
e3c68b
+enum libcvlt_mem_types_ {
e3c68b
+    gf_libcvlt_mt_cvlt_private_t = gf_common_mt_end + 1,
e3c68b
+    gf_libcvlt_mt_end
e3c68b
+};
e3c68b
+#endif /* __LIBCVLT_MEM_TYPES_H__ */
e3c68b
diff --git a/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/libcvlt.c b/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/libcvlt.c
e3c68b
new file mode 100644
e3c68b
index 0000000..e827882
e3c68b
--- /dev/null
e3c68b
+++ b/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/libcvlt.c
e3c68b
@@ -0,0 +1,842 @@
e3c68b
+#include <stdlib.h>
e3c68b
+#include <glusterfs/xlator.h>
e3c68b
+#include <glusterfs/glusterfs.h>
e3c68b
+#include "libcvlt.h"
e3c68b
+#include "cloudsync-common.h"
e3c68b
+#include "cvlt-messages.h"
e3c68b
+
e3c68b
+#define LIBARCHIVE_SO "libopenarchive.so"
e3c68b
+#define ALIGN_SIZE 4096
e3c68b
+#define CVLT_TRAILER "cvltv1"
e3c68b
+
e3c68b
+store_methods_t store_ops = {
e3c68b
+    .fop_download = cvlt_download,
e3c68b
+    .fop_init = cvlt_init,
e3c68b
+    .fop_reconfigure = cvlt_reconfigure,
e3c68b
+    .fop_fini = cvlt_fini,
e3c68b
+    .fop_remote_read = cvlt_read,
e3c68b
+};
e3c68b
+
e3c68b
+static const int32_t num_req = 32;
e3c68b
+static const int32_t num_iatt = 32;
e3c68b
+static char *plugin = "cvlt_cloudSync";
e3c68b
+
e3c68b
+int32_t
e3c68b
+mem_acct_init(xlator_t *this)
e3c68b
+{
e3c68b
+    int ret = -1;
e3c68b
+
e3c68b
+    if (!this)
e3c68b
+        return ret;
e3c68b
+
e3c68b
+    ret = xlator_mem_acct_init(this, gf_libcvlt_mt_end + 1);
e3c68b
+
e3c68b
+    if (ret != 0) {
e3c68b
+        return ret;
e3c68b
+    }
e3c68b
+
e3c68b
+    return ret;
e3c68b
+}
e3c68b
+
e3c68b
+static void
e3c68b
+cvlt_free_resources(archive_t *arch)
e3c68b
+{
e3c68b
+    /*
e3c68b
+     * We will release all the resources that were allocated by the xlator.
e3c68b
+     * Check whether there are any buffers which have not been released
e3c68b
+     * back to a mempool.
e3c68b
+     */
e3c68b
+
e3c68b
+    if (arch->handle) {
e3c68b
+        dlclose(arch->handle);
e3c68b
+    }
e3c68b
+
e3c68b
+    if (arch->iobuf_pool) {
e3c68b
+        iobuf_pool_destroy(arch->iobuf_pool);
e3c68b
+    }
e3c68b
+
e3c68b
+    if (arch->req_pool) {
e3c68b
+        mem_pool_destroy(arch->req_pool);
e3c68b
+        arch->req_pool = NULL;
e3c68b
+    }
e3c68b
+
e3c68b
+    return;
e3c68b
+}
e3c68b
+
e3c68b
+static int32_t
e3c68b
+cvlt_extract_store_fops(xlator_t *this, archive_t *arch)
e3c68b
+{
e3c68b
+    int32_t op_ret = -1;
e3c68b
+    get_archstore_methods_t get_archstore_methods;
e3c68b
+
e3c68b
+    /*
e3c68b
+     * libopenarchive.so defines methods for performing data management
e3c68b
+     * operations. We will extract the methods from library and these
e3c68b
+     * methods will be invoked for moving data between glusterfs volume
e3c68b
+     * and the data management product.
e3c68b
+     */
e3c68b
+
e3c68b
+    VALIDATE_OR_GOTO(arch, err);
e3c68b
+
e3c68b
+    arch->handle = dlopen(LIBARCHIVE_SO, RTLD_NOW);
e3c68b
+    if (!arch->handle) {
e3c68b
+        gf_msg(plugin, GF_LOG_ERROR, 0, CVLT_DLOPEN_FAILED,
e3c68b
+               " failed to open %s ", LIBARCHIVE_SO);
e3c68b
+        return op_ret;
e3c68b
+    }
e3c68b
+
e3c68b
+    dlerror(); /* Clear any existing error */
e3c68b
+
e3c68b
+    get_archstore_methods = dlsym(arch->handle, "get_archstore_methods");
e3c68b
+    if (!get_archstore_methods) {
e3c68b
+        gf_msg(plugin, GF_LOG_ERROR, 0, CVLT_EXTRACTION_FAILED,
e3c68b
+               " Error extracting get_archstore_methods()");
e3c68b
+        dlclose(arch->handle);
e3c68b
+        arch->handle = NULL;
e3c68b
+        return op_ret;
e3c68b
+    }
e3c68b
+
e3c68b
+    op_ret = get_archstore_methods(&(arch->fops));
e3c68b
+    if (op_ret) {
e3c68b
+        gf_msg(plugin, GF_LOG_ERROR, 0, CVLT_EXTRACTION_FAILED,
e3c68b
+               " Failed to extract methods in get_archstore_methods");
e3c68b
+        dlclose(arch->handle);
e3c68b
+        arch->handle = NULL;
e3c68b
+        return op_ret;
e3c68b
+    }
e3c68b
+
e3c68b
+err:
e3c68b
+    return op_ret;
e3c68b
+}
e3c68b
+
e3c68b
+static int32_t
e3c68b
+cvlt_alloc_resources(xlator_t *this, archive_t *arch, int num_req, int num_iatt)
e3c68b
+{
e3c68b
+    /*
e3c68b
+     * Initialize information about all the memory pools that will be
e3c68b
+     * used by this xlator.
e3c68b
+     */
e3c68b
+    arch->nreqs = 0;
e3c68b
+
e3c68b
+    arch->req_pool = NULL;
e3c68b
+
e3c68b
+    arch->handle = NULL;
e3c68b
+    arch->xl = this;
e3c68b
+
e3c68b
+    arch->req_pool = mem_pool_new(cvlt_request_t, num_req);
e3c68b
+    if (!arch->req_pool) {
e3c68b
+        goto err;
e3c68b
+    }
e3c68b
+
e3c68b
+    arch->iobuf_pool = iobuf_pool_new();
e3c68b
+    if (!arch->iobuf_pool) {
e3c68b
+        goto err;
e3c68b
+    }
e3c68b
+
e3c68b
+    if (cvlt_extract_store_fops(this, arch)) {
e3c68b
+        goto err;
e3c68b
+    }
e3c68b
+
e3c68b
+    return 0;
e3c68b
+
e3c68b
+err:
e3c68b
+
e3c68b
+    return -1;
e3c68b
+}
e3c68b
+
e3c68b
+static void
e3c68b
+cvlt_req_init(cvlt_request_t *req)
e3c68b
+{
e3c68b
+    sem_init(&(req->sem), 0, 0);
e3c68b
+
e3c68b
+    return;
e3c68b
+}
e3c68b
+
e3c68b
+static void
e3c68b
+cvlt_req_destroy(cvlt_request_t *req)
e3c68b
+{
e3c68b
+    if (req->iobuf) {
e3c68b
+        iobuf_unref(req->iobuf);
e3c68b
+    }
e3c68b
+
e3c68b
+    if (req->iobref) {
e3c68b
+        iobref_unref(req->iobref);
e3c68b
+    }
e3c68b
+
e3c68b
+    sem_destroy(&(req->sem));
e3c68b
+
e3c68b
+    return;
e3c68b
+}
e3c68b
+
e3c68b
+static cvlt_request_t *
e3c68b
+cvlt_alloc_req(archive_t *arch)
e3c68b
+{
e3c68b
+    cvlt_request_t *reqptr = NULL;
e3c68b
+
e3c68b
+    if (!arch) {
e3c68b
+        goto err;
e3c68b
+    }
e3c68b
+
e3c68b
+    if (arch->req_pool) {
e3c68b
+        reqptr = mem_get0(arch->req_pool);
e3c68b
+        if (reqptr) {
e3c68b
+            cvlt_req_init(reqptr);
e3c68b
+        }
e3c68b
+    }
e3c68b
+
e3c68b
+    if (reqptr) {
e3c68b
+        LOCK(&(arch->lock));
e3c68b
+        arch->nreqs++;
e3c68b
+        UNLOCK(&(arch->lock));
e3c68b
+    }
e3c68b
+
e3c68b
+err:
e3c68b
+    return reqptr;
e3c68b
+}
e3c68b
+
e3c68b
+static int32_t
e3c68b
+cvlt_free_req(archive_t *arch, cvlt_request_t *reqptr)
e3c68b
+{
e3c68b
+    if (!reqptr) {
e3c68b
+        goto err;
e3c68b
+    }
e3c68b
+
e3c68b
+    if (!arch) {
e3c68b
+        goto err;
e3c68b
+    }
e3c68b
+
e3c68b
+    if (arch->req_pool) {
e3c68b
+        /*
e3c68b
+         * Free the request resources if they exist.
e3c68b
+         */
e3c68b
+
e3c68b
+        cvlt_req_destroy(reqptr);
e3c68b
+        mem_put(reqptr);
e3c68b
+
e3c68b
+        LOCK(&(arch->lock));
e3c68b
+        arch->nreqs--;
e3c68b
+        UNLOCK(&(arch->lock));
e3c68b
+    }
e3c68b
+
e3c68b
+    return 0;
e3c68b
+
e3c68b
+err:
e3c68b
+    return -1;
e3c68b
+}
e3c68b
+
e3c68b
+static int32_t
e3c68b
+cvlt_init_xlator(xlator_t *this, archive_t *arch, int num_req, int num_iatt)
e3c68b
+{
e3c68b
+    int32_t ret = -1;
e3c68b
+    int32_t errnum = -1;
e3c68b
+    int32_t locked = 0;
e3c68b
+
e3c68b
+    /*
e3c68b
+     * Perform all the initializations needed for brining up the xlator.
e3c68b
+     */
e3c68b
+    if (!arch) {
e3c68b
+        goto err;
e3c68b
+    }
e3c68b
+
e3c68b
+    LOCK_INIT(&(arch->lock));
e3c68b
+    LOCK(&(arch->lock));
e3c68b
+
e3c68b
+    locked = 1;
e3c68b
+
e3c68b
+    ret = cvlt_alloc_resources(this, arch, num_req, num_iatt);
e3c68b
+
e3c68b
+    if (ret) {
e3c68b
+        goto err;
e3c68b
+    }
e3c68b
+
e3c68b
+    /*
e3c68b
+     * Now that the fops have been extracted initialize the store
e3c68b
+     */
e3c68b
+    ret = arch->fops.init(&(arch->descinfo), &errnum, plugin);
e3c68b
+    if (ret) {
e3c68b
+        goto err;
e3c68b
+    }
e3c68b
+
e3c68b
+    UNLOCK(&(arch->lock));
e3c68b
+    locked = 0;
e3c68b
+    ret = 0;
e3c68b
+
e3c68b
+    return ret;
e3c68b
+
e3c68b
+err:
e3c68b
+    cvlt_free_resources(arch);
e3c68b
+
e3c68b
+    if (locked) {
e3c68b
+        UNLOCK(&(arch->lock));
e3c68b
+    }
e3c68b
+
e3c68b
+    return ret;
e3c68b
+}
e3c68b
+
e3c68b
+static int32_t
e3c68b
+cvlt_term_xlator(archive_t *arch)
e3c68b
+{
e3c68b
+    int32_t errnum = -1;
e3c68b
+
e3c68b
+    if (!arch) {
e3c68b
+        goto err;
e3c68b
+    }
e3c68b
+
e3c68b
+    LOCK(&(arch->lock));
e3c68b
+
e3c68b
+    /*
e3c68b
+     * Release the resources that have been allocated inside store
e3c68b
+     */
e3c68b
+    arch->fops.fini(&(arch->descinfo), &errnum);
e3c68b
+
e3c68b
+    cvlt_free_resources(arch);
e3c68b
+
e3c68b
+    UNLOCK(&(arch->lock));
e3c68b
+
e3c68b
+    GF_FREE(arch);
e3c68b
+
e3c68b
+    return 0;
e3c68b
+
e3c68b
+err:
e3c68b
+    return -1;
e3c68b
+}
e3c68b
+
e3c68b
+static int32_t
e3c68b
+cvlt_init_store_info(archive_t *priv, archstore_info_t *store_info)
e3c68b
+{
e3c68b
+    if (!store_info) {
e3c68b
+        return -1;
e3c68b
+    }
e3c68b
+
e3c68b
+    store_info->prod = priv->product_id;
e3c68b
+    store_info->prodlen = strlen(priv->product_id);
e3c68b
+
e3c68b
+    store_info->id = priv->store_id;
e3c68b
+    store_info->idlen = strlen(priv->store_id);
e3c68b
+
e3c68b
+    return 0;
e3c68b
+}
e3c68b
+
e3c68b
+static int32_t
e3c68b
+cvlt_init_file_info(cs_loc_xattr_t *xattr, archstore_fileinfo_t *file_info)
e3c68b
+{
e3c68b
+    if (!xattr || !file_info) {
e3c68b
+        return -1;
e3c68b
+    }
e3c68b
+
e3c68b
+    gf_uuid_copy(file_info->uuid, xattr->uuid);
e3c68b
+    file_info->path = xattr->file_path;
e3c68b
+    file_info->pathlength = strlen(xattr->file_path);
e3c68b
+
e3c68b
+    return 0;
e3c68b
+}
e3c68b
+
e3c68b
+static int32_t
e3c68b
+cvlt_init_gluster_store_info(cs_loc_xattr_t *xattr,
e3c68b
+                             archstore_info_t *store_info)
e3c68b
+{
e3c68b
+    static char *product = "glusterfs";
e3c68b
+
e3c68b
+    if (!xattr || !store_info) {
e3c68b
+        return -1;
e3c68b
+    }
e3c68b
+
e3c68b
+    store_info->prod = product;
e3c68b
+    store_info->prodlen = strlen(product);
e3c68b
+
e3c68b
+    store_info->id = xattr->volname;
e3c68b
+    store_info->idlen = strlen(xattr->volname);
e3c68b
+
e3c68b
+    return 0;
e3c68b
+}
e3c68b
+
e3c68b
+static int32_t
e3c68b
+cvlt_init_gluster_file_info(cs_loc_xattr_t *xattr,
e3c68b
+                            archstore_fileinfo_t *file_info)
e3c68b
+{
e3c68b
+    if (!xattr || !file_info) {
e3c68b
+        return -1;
e3c68b
+    }
e3c68b
+
e3c68b
+    gf_uuid_copy(file_info->uuid, xattr->gfid);
e3c68b
+    file_info->path = xattr->file_path;
e3c68b
+    file_info->pathlength = strlen(xattr->file_path);
e3c68b
+
e3c68b
+    return 0;
e3c68b
+}
e3c68b
+
e3c68b
+static void
e3c68b
+cvlt_copy_stat_info(struct iatt *buf, cs_size_xattr_t *xattrs)
e3c68b
+{
e3c68b
+    /*
e3c68b
+     * If the file was archived then the reported size will not be a
e3c68b
+     * correct one. We need to fix this.
e3c68b
+     */
e3c68b
+    if (buf && xattrs) {
e3c68b
+        buf->ia_size = xattrs->size;
e3c68b
+        buf->ia_blksize = xattrs->blksize;
e3c68b
+        buf->ia_blocks = xattrs->blocks;
e3c68b
+    }
e3c68b
+
e3c68b
+    return;
e3c68b
+}
e3c68b
+
e3c68b
+static void
e3c68b
+cvlt_readv_complete(archstore_desc_t *desc, app_callback_info_t *cbkinfo,
e3c68b
+                    void *cookie, int64_t op_ret, int32_t op_errno)
e3c68b
+{
e3c68b
+    struct iovec iov;
e3c68b
+    xlator_t *this = NULL;
e3c68b
+    struct iatt postbuf = {
e3c68b
+        0,
e3c68b
+    };
e3c68b
+    call_frame_t *frame = NULL;
e3c68b
+    cvlt_request_t *req = (cvlt_request_t *)cookie;
e3c68b
+    cs_local_t *local = NULL;
e3c68b
+    cs_private_t *cspriv = NULL;
e3c68b
+    archive_t *priv = NULL;
e3c68b
+
e3c68b
+    frame = req->frame;
e3c68b
+    this = frame->this;
e3c68b
+    local = frame->local;
e3c68b
+
e3c68b
+    cspriv = this->private;
e3c68b
+    priv = (archive_t *)cspriv->stores->config;
e3c68b
+
e3c68b
+    if (strcmp(priv->trailer, CVLT_TRAILER)) {
e3c68b
+        op_ret = -1;
e3c68b
+        op_errno = EINVAL;
e3c68b
+        goto out;
e3c68b
+    }
e3c68b
+
e3c68b
+    gf_msg_debug(plugin, 0,
e3c68b
+                 " Read callback invoked offset:%" PRIu64 "bytes: %" PRIu64
e3c68b
+                 " op : %d ret : %" PRId64 " errno : %d",
e3c68b
+                 req->offset, req->bytes, req->op_type, op_ret, op_errno);
e3c68b
+
e3c68b
+    if (op_ret < 0) {
e3c68b
+        goto out;
e3c68b
+    }
e3c68b
+
e3c68b
+    req->iobref = iobref_new();
e3c68b
+    if (!req->iobref) {
e3c68b
+        op_ret = -1;
e3c68b
+        op_errno = ENOMEM;
e3c68b
+        goto out;
e3c68b
+    }
e3c68b
+
e3c68b
+    iobref_add(req->iobref, req->iobuf);
e3c68b
+    iov.iov_base = iobuf_ptr(req->iobuf);
e3c68b
+    iov.iov_len = op_ret;
e3c68b
+
e3c68b
+    cvlt_copy_stat_info(&postbuf, &(req->szxattr));
e3c68b
+
e3c68b
+    /*
e3c68b
+     * Hack to notify higher layers of EOF.
e3c68b
+     */
e3c68b
+    if (!postbuf.ia_size || (req->offset + iov.iov_len >= postbuf.ia_size)) {
e3c68b
+        gf_msg_debug(plugin, 0, " signalling end-of-file for uuid=%s",
e3c68b
+                     uuid_utoa(req->file_info.uuid));
e3c68b
+        op_errno = ENOENT;
e3c68b
+    }
e3c68b
+
e3c68b
+out:
e3c68b
+
e3c68b
+    STACK_UNWIND_STRICT(readv, frame, op_ret, op_errno, &iov, 1, &postbuf,
e3c68b
+                        req->iobref, local->xattr_rsp);
e3c68b
+
e3c68b
+    if (req) {
e3c68b
+        cvlt_free_req(priv, req);
e3c68b
+    }
e3c68b
+
e3c68b
+    return;
e3c68b
+}
e3c68b
+
e3c68b
+static void
e3c68b
+cvlt_download_complete(archstore_desc_t *store, app_callback_info_t *cbk_info,
e3c68b
+                       void *cookie, int64_t ret, int errcode)
e3c68b
+{
e3c68b
+    cvlt_request_t *req = (cvlt_request_t *)cookie;
e3c68b
+
e3c68b
+    gf_msg_debug(plugin, 0,
e3c68b
+                 " Download callback invoked  ret : %" PRId64 " errno : %d",
e3c68b
+                 ret, errcode);
e3c68b
+
e3c68b
+    req->op_ret = ret;
e3c68b
+    req->op_errno = errcode;
e3c68b
+    sem_post(&(req->sem));
e3c68b
+
e3c68b
+    return;
e3c68b
+}
e3c68b
+
e3c68b
+void *
e3c68b
+cvlt_init(xlator_t *this)
e3c68b
+{
e3c68b
+    int ret = 0;
e3c68b
+    archive_t *priv = NULL;
e3c68b
+
e3c68b
+    if (!this->children || this->children->next) {
e3c68b
+        gf_msg(plugin, GF_LOG_ERROR, ENOMEM, 0,
e3c68b
+               "should have exactly one child");
e3c68b
+        ret = -1;
e3c68b
+        goto out;
e3c68b
+    }
e3c68b
+
e3c68b
+    if (!this->parents) {
e3c68b
+        gf_msg(plugin, GF_LOG_ERROR, ENOMEM, 0,
e3c68b
+               "dangling volume. check volfile");
e3c68b
+        ret = -1;
e3c68b
+        goto out;
e3c68b
+    }
e3c68b
+
e3c68b
+    priv = GF_CALLOC(1, sizeof(archive_t), gf_libcvlt_mt_cvlt_private_t);
e3c68b
+    if (!priv) {
e3c68b
+        ret = -1;
e3c68b
+        goto out;
e3c68b
+    }
e3c68b
+
e3c68b
+    priv->trailer = CVLT_TRAILER;
e3c68b
+    if (cvlt_init_xlator(this, priv, num_req, num_iatt)) {
e3c68b
+        gf_msg(plugin, GF_LOG_ERROR, ENOMEM, 0, "xlator init failed");
e3c68b
+        ret = -1;
e3c68b
+        goto out;
e3c68b
+    }
e3c68b
+
e3c68b
+    GF_OPTION_INIT("cloudsync-store-id", priv->store_id, str, out);
e3c68b
+    GF_OPTION_INIT("cloudsync-product-id", priv->product_id, str, out);
e3c68b
+
e3c68b
+    gf_msg(plugin, GF_LOG_INFO, 0, 0,
e3c68b
+           "store id is : %s "
e3c68b
+           "product id is : %s.",
e3c68b
+           priv->store_id, priv->product_id);
e3c68b
+out:
e3c68b
+    if (ret == -1) {
e3c68b
+        cvlt_term_xlator(priv);
e3c68b
+        return (NULL);
e3c68b
+    }
e3c68b
+    return priv;
e3c68b
+}
e3c68b
+
e3c68b
+int
e3c68b
+cvlt_reconfigure(xlator_t *this, dict_t *options)
e3c68b
+{
e3c68b
+    cs_private_t *cspriv = NULL;
e3c68b
+    archive_t *priv = NULL;
e3c68b
+
e3c68b
+    cspriv = this->private;
e3c68b
+    priv = (archive_t *)cspriv->stores->config;
e3c68b
+
e3c68b
+    if (strcmp(priv->trailer, CVLT_TRAILER))
e3c68b
+        goto out;
e3c68b
+
e3c68b
+    GF_OPTION_RECONF("cloudsync-store-id", priv->store_id, options, str, out);
e3c68b
+
e3c68b
+    GF_OPTION_RECONF("cloudsync-product-id", priv->product_id, options, str,
e3c68b
+                     out);
e3c68b
+    gf_msg_debug(plugin, 0,
e3c68b
+                 "store id is : %s "
e3c68b
+                 "product id is : %s.",
e3c68b
+                 priv->store_id, priv->product_id);
e3c68b
+    return 0;
e3c68b
+out:
e3c68b
+    return -1;
e3c68b
+}
e3c68b
+
e3c68b
+void
e3c68b
+cvlt_fini(void *config)
e3c68b
+{
e3c68b
+    archive_t *priv = NULL;
e3c68b
+
e3c68b
+    priv = (archive_t *)config;
e3c68b
+
e3c68b
+    if (strcmp(priv->trailer, CVLT_TRAILER))
e3c68b
+        return;
e3c68b
+
e3c68b
+    cvlt_term_xlator(priv);
e3c68b
+    gf_msg(plugin, GF_LOG_INFO, 0, CVLT_FREE, " released xlator resources");
e3c68b
+    return;
e3c68b
+}
e3c68b
+
e3c68b
+int
e3c68b
+cvlt_download(call_frame_t *frame, void *config)
e3c68b
+{
e3c68b
+    archive_t *parch = NULL;
e3c68b
+    cs_local_t *local = frame->local;
e3c68b
+    cs_loc_xattr_t *locxattr = local->xattrinfo.lxattr;
e3c68b
+    cvlt_request_t *req = NULL;
e3c68b
+    archstore_info_t dest_storeinfo;
e3c68b
+    archstore_fileinfo_t dest_fileinfo;
e3c68b
+    int32_t op_ret, op_errno;
e3c68b
+
e3c68b
+    parch = (archive_t *)config;
e3c68b
+
e3c68b
+    if (strcmp(parch->trailer, CVLT_TRAILER)) {
e3c68b
+        op_ret = -1;
e3c68b
+        op_errno = EINVAL;
e3c68b
+        goto err;
e3c68b
+    }
e3c68b
+
e3c68b
+    gf_msg_debug(plugin, 0, " download invoked for uuid = %s  gfid=%s ",
e3c68b
+                 locxattr->uuid, uuid_utoa(locxattr->gfid));
e3c68b
+
e3c68b
+    if (!(parch->fops.restore)) {
e3c68b
+        op_errno = ELIBBAD;
e3c68b
+        goto err;
e3c68b
+    }
e3c68b
+
e3c68b
+    /*
e3c68b
+     * Download needs to be processed. Allocate a request.
e3c68b
+     */
e3c68b
+    req = cvlt_alloc_req(parch);
e3c68b
+
e3c68b
+    if (!req) {
e3c68b
+        gf_msg(plugin, GF_LOG_ERROR, ENOMEM, CVLT_RESOURCE_ALLOCATION_FAILED,
e3c68b
+               " failed to allocated request for gfid=%s",
e3c68b
+               uuid_utoa(locxattr->gfid));
e3c68b
+        op_errno = ENOMEM;
e3c68b
+        goto err;
e3c68b
+    }
e3c68b
+
e3c68b
+    /*
e3c68b
+     * Initialize the request object.
e3c68b
+     */
e3c68b
+    req->op_type = CVLT_RESTORE_OP;
e3c68b
+    req->frame = frame;
e3c68b
+
e3c68b
+    /*
e3c68b
+     * The file is currently residing inside a data management store.
e3c68b
+     * To restore the file contents we need to provide the information
e3c68b
+     * about data management store.
e3c68b
+     */
e3c68b
+    op_ret = cvlt_init_store_info(parch, &(req->store_info));
e3c68b
+    if (op_ret < 0) {
e3c68b
+        gf_msg(plugin, GF_LOG_ERROR, 0, CVLT_EXTRACTION_FAILED,
e3c68b
+               " failed to extract store info for gfid=%s",
e3c68b
+               uuid_utoa(locxattr->gfid));
e3c68b
+        goto err;
e3c68b
+    }
e3c68b
+
e3c68b
+    op_ret = cvlt_init_file_info(locxattr, &(req->file_info));
e3c68b
+    if (op_ret < 0) {
e3c68b
+        gf_msg(plugin, GF_LOG_ERROR, 0, CVLT_EXTRACTION_FAILED,
e3c68b
+               " failed to extract file info for gfid=%s",
e3c68b
+               uuid_utoa(locxattr->gfid));
e3c68b
+        goto err;
e3c68b
+    }
e3c68b
+
e3c68b
+    /*
e3c68b
+     * We need t perform in-place restore of the file from data managment
e3c68b
+     * store to gusterfs volume.
e3c68b
+     */
e3c68b
+    op_ret = cvlt_init_gluster_store_info(locxattr, &dest_storeinfo);
e3c68b
+    if (op_ret < 0) {
e3c68b
+        gf_msg(plugin, GF_LOG_ERROR, 0, CVLT_EXTRACTION_FAILED,
e3c68b
+               " failed to extract destination store info for gfid=%s",
e3c68b
+               uuid_utoa(locxattr->gfid));
e3c68b
+        goto err;
e3c68b
+    }
e3c68b
+
e3c68b
+    op_ret = cvlt_init_gluster_file_info(locxattr, &dest_fileinfo);
e3c68b
+    if (op_ret < 0) {
e3c68b
+        gf_msg(plugin, GF_LOG_ERROR, 0, CVLT_EXTRACTION_FAILED,
e3c68b
+               " failed to extract file info for gfid=%s",
e3c68b
+               uuid_utoa(locxattr->gfid));
e3c68b
+        goto err;
e3c68b
+    }
e3c68b
+
e3c68b
+    /*
e3c68b
+     * Submit the restore request.
e3c68b
+     */
e3c68b
+    op_ret = parch->fops.restore(&(parch->descinfo), &(req->store_info),
e3c68b
+                                 &(req->file_info), &dest_storeinfo,
e3c68b
+                                 &dest_fileinfo, &op_errno,
e3c68b
+                                 cvlt_download_complete, req);
e3c68b
+    if (op_ret < 0) {
e3c68b
+        gf_msg(plugin, GF_LOG_ERROR, 0, CVLT_RESTORE_FAILED,
e3c68b
+               " failed to restore file gfid=%s from data managment store",
e3c68b
+               uuid_utoa(locxattr->gfid));
e3c68b
+        goto err;
e3c68b
+    }
e3c68b
+
e3c68b
+    /*
e3c68b
+     * Wait for the restore to complete.
e3c68b
+     */
e3c68b
+    sem_wait(&(req->sem));
e3c68b
+
e3c68b
+    if (req->op_ret < 0) {
e3c68b
+        gf_msg(plugin, GF_LOG_ERROR, 0, CVLT_RESTORE_FAILED,
e3c68b
+               " restored failed for gfid=%s", uuid_utoa(locxattr->gfid));
e3c68b
+        goto err;
e3c68b
+    }
e3c68b
+
e3c68b
+    if (req) {
e3c68b
+        cvlt_free_req(parch, req);
e3c68b
+    }
e3c68b
+
e3c68b
+    return 0;
e3c68b
+
e3c68b
+err:
e3c68b
+
e3c68b
+    if (req) {
e3c68b
+        cvlt_free_req(parch, req);
e3c68b
+    }
e3c68b
+
e3c68b
+    return -1;
e3c68b
+}
e3c68b
+
e3c68b
+int
e3c68b
+cvlt_read(call_frame_t *frame, void *config)
e3c68b
+{
e3c68b
+    int32_t op_ret = -1;
e3c68b
+    int32_t op_errno = 0;
e3c68b
+    archive_t *parch = NULL;
e3c68b
+    cvlt_request_t *req = NULL;
e3c68b
+    struct iovec iov = {
e3c68b
+        0,
e3c68b
+    };
e3c68b
+    struct iobref *iobref;
e3c68b
+    size_t size = 0;
e3c68b
+    off_t off = 0;
e3c68b
+
e3c68b
+    cs_local_t *local = frame->local;
e3c68b
+    cs_loc_xattr_t *locxattr = local->xattrinfo.lxattr;
e3c68b
+
e3c68b
+    size = local->xattrinfo.size;
e3c68b
+    off = local->xattrinfo.offset;
e3c68b
+
e3c68b
+    parch = (archive_t *)config;
e3c68b
+
e3c68b
+    if (strcmp(parch->trailer, CVLT_TRAILER)) {
e3c68b
+        op_ret = -1;
e3c68b
+        op_errno = EINVAL;
e3c68b
+        goto err;
e3c68b
+    }
e3c68b
+
e3c68b
+    gf_msg_debug(plugin, 0,
e3c68b
+                 " read invoked for gfid = %s offset = %" PRIu64
e3c68b
+                 " file_size = %" PRIu64,
e3c68b
+                 uuid_utoa(locxattr->gfid), off, local->stbuf.ia_size);
e3c68b
+
e3c68b
+    if (off >= local->stbuf.ia_size) {
e3c68b
+        /*
e3c68b
+         * Hack to notify higher layers of EOF.
e3c68b
+         */
e3c68b
+
e3c68b
+        op_errno = ENOENT;
e3c68b
+        op_ret = 0;
e3c68b
+
e3c68b
+        gf_msg(plugin, GF_LOG_ERROR, 0, CVLT_READ_FAILED,
e3c68b
+               " reporting end-of-file for gfid=%s", uuid_utoa(locxattr->gfid));
e3c68b
+
e3c68b
+        goto err;
e3c68b
+    }
e3c68b
+
e3c68b
+    if (!size) {
e3c68b
+        op_errno = EINVAL;
e3c68b
+
e3c68b
+        gf_msg(plugin, GF_LOG_ERROR, 0, CVLT_READ_FAILED,
e3c68b
+               " zero size read attempted on gfid=%s",
e3c68b
+               uuid_utoa(locxattr->gfid));
e3c68b
+        goto err;
e3c68b
+    }
e3c68b
+
e3c68b
+    if (!(parch->fops.read)) {
e3c68b
+        op_errno = ELIBBAD;
e3c68b
+        goto err;
e3c68b
+    }
e3c68b
+
e3c68b
+    /*
e3c68b
+     * The read request need to be processed. Allocate a request.
e3c68b
+     */
e3c68b
+    req = cvlt_alloc_req(parch);
e3c68b
+
e3c68b
+    if (!req) {
e3c68b
+        gf_msg(plugin, GF_LOG_ERROR, ENOMEM, CVLT_NO_MEMORY,
e3c68b
+               " failed to allocated request for gfid=%s",
e3c68b
+               uuid_utoa(locxattr->gfid));
e3c68b
+        op_errno = ENOMEM;
e3c68b
+        goto err;
e3c68b
+    }
e3c68b
+
e3c68b
+    req->iobuf = iobuf_get_page_aligned(parch->iobuf_pool, size, ALIGN_SIZE);
e3c68b
+    if (!req->iobuf) {
e3c68b
+        op_errno = ENOMEM;
e3c68b
+        goto err;
e3c68b
+    }
e3c68b
+
e3c68b
+    /*
e3c68b
+     * Initialize the request object.
e3c68b
+     */
e3c68b
+    req->op_type = CVLT_READ_OP;
e3c68b
+    req->offset = off;
e3c68b
+    req->bytes = size;
e3c68b
+    req->frame = frame;
e3c68b
+    req->szxattr.size = local->stbuf.ia_size;
e3c68b
+    req->szxattr.blocks = local->stbuf.ia_blocks;
e3c68b
+    req->szxattr.blksize = local->stbuf.ia_blksize;
e3c68b
+
e3c68b
+    /*
e3c68b
+     * The file is currently residing inside a data management store.
e3c68b
+     * To read the file contents we need to provide the information
e3c68b
+     * about data management store.
e3c68b
+     */
e3c68b
+    op_ret = cvlt_init_store_info(parch, &(req->store_info));
e3c68b
+    if (op_ret < 0) {
e3c68b
+        gf_msg(plugin, GF_LOG_ERROR, 0, CVLT_EXTRACTION_FAILED,
e3c68b
+               " failed to extract store info for gfid=%s"
e3c68b
+               " offset=%" PRIu64 " size=%" GF_PRI_SIZET
e3c68b
+               ", "
e3c68b
+               " buf=%p",
e3c68b
+               uuid_utoa(locxattr->gfid), off, size, req->iobuf->ptr);
e3c68b
+        goto err;
e3c68b
+    }
e3c68b
+
e3c68b
+    op_ret = cvlt_init_file_info(locxattr, &(req->file_info));
e3c68b
+    if (op_ret < 0) {
e3c68b
+        gf_msg(plugin, GF_LOG_ERROR, 0, CVLT_EXTRACTION_FAILED,
e3c68b
+               " failed to extract file info for gfid=%s"
e3c68b
+               " offset=%" PRIu64 " size=%" GF_PRI_SIZET
e3c68b
+               ", "
e3c68b
+               " buf=%p",
e3c68b
+               uuid_utoa(locxattr->gfid), off, size, req->iobuf->ptr);
e3c68b
+        goto err;
e3c68b
+    }
e3c68b
+
e3c68b
+    /*
e3c68b
+     * Submit the read request.
e3c68b
+     */
e3c68b
+    op_ret = parch->fops.read(&(parch->descinfo), &(req->store_info),
e3c68b
+                              &(req->file_info), off, req->iobuf->ptr, size,
e3c68b
+                              &op_errno, cvlt_readv_complete, req);
e3c68b
+
e3c68b
+    if (op_ret < 0) {
e3c68b
+        gf_msg(plugin, GF_LOG_ERROR, 0, CVLT_EXTRACTION_FAILED,
e3c68b
+               " read failed on gfid=%s"
e3c68b
+               " offset=%" PRIu64 " size=%" GF_PRI_SIZET
e3c68b
+               ", "
e3c68b
+               " buf=%p",
e3c68b
+               uuid_utoa(locxattr->gfid), off, size, req->iobuf->ptr);
e3c68b
+        goto err;
e3c68b
+    }
e3c68b
+
e3c68b
+    return 0;
e3c68b
+
e3c68b
+err:
e3c68b
+
e3c68b
+    iobref = iobref_new();
e3c68b
+    gf_msg_debug(plugin, 0, " read unwinding stack op_ret = %d, op_errno = %d",
e3c68b
+                 op_ret, op_errno);
e3c68b
+
e3c68b
+    STACK_UNWIND_STRICT(readv, frame, op_ret, op_errno, &iov, 1,
e3c68b
+                        &(local->stbuf), iobref, local->xattr_rsp);
e3c68b
+
e3c68b
+    if (iobref) {
e3c68b
+        iobref_unref(iobref);
e3c68b
+    }
e3c68b
+
e3c68b
+    if (req) {
e3c68b
+        cvlt_free_req(parch, req);
e3c68b
+    }
e3c68b
+
e3c68b
+    return 0;
e3c68b
+}
e3c68b
diff --git a/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/libcvlt.h b/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/libcvlt.h
e3c68b
new file mode 100644
e3c68b
index 0000000..c45ac94
e3c68b
--- /dev/null
e3c68b
+++ b/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/libcvlt.h
e3c68b
@@ -0,0 +1,84 @@
e3c68b
+/*
e3c68b
+  Copyright (c) 2018 Commvault Systems, Inc. <http://www.commvault.com>
e3c68b
+  This file is part of GlusterFS.
e3c68b
+
e3c68b
+  This file is licensed to you under your choice of the GNU Lesser
e3c68b
+  General Public License, version 3 or any later version (LGPLv3 or
e3c68b
+  later), or the GNU General Public License, version 2 (GPLv2), in all
e3c68b
+  cases as published by the Free Software Foundation.
e3c68b
+*/
e3c68b
+#ifndef _LIBCVLT_H
e3c68b
+#define _LIBCVLT_H
e3c68b
+
e3c68b
+#include <semaphore.h>
e3c68b
+#include <glusterfs/xlator.h>
e3c68b
+#include <glusterfs/glusterfs.h>
e3c68b
+#include <glusterfs/call-stub.h>
e3c68b
+#include <glusterfs/syncop.h>
e3c68b
+#include <glusterfs/compat-errno.h>
e3c68b
+#include "cloudsync-common.h"
e3c68b
+#include "libcvlt-mem-types.h"
e3c68b
+#include "archivestore.h"
e3c68b
+
e3c68b
+enum _cvlt_op {
e3c68b
+    CVLT_READ_OP = 1,
e3c68b
+    CVLT_WRITE_OP = 2,
e3c68b
+    CVLT_RESTORE_OP = 3,
e3c68b
+    CVLT_ARCHIVE_OP = 4,
e3c68b
+    CVLT_LOOKUP_OP = 5,
e3c68b
+    CVLT_XATTR_OP = 6,
e3c68b
+    CVLT_STAT_OP = 7,
e3c68b
+    CVLT_FSTAT_op = 8,
e3c68b
+    CVLT_UNDEF_OP = 127
e3c68b
+};
e3c68b
+typedef enum _cvlt_op cvlt_op_t;
e3c68b
+
e3c68b
+struct _archive;
e3c68b
+struct _cvlt_request {
e3c68b
+    uint64_t offset;
e3c68b
+    uint64_t bytes;
e3c68b
+    struct iobuf *iobuf;
e3c68b
+    struct iobref *iobref;
e3c68b
+    call_frame_t *frame;
e3c68b
+    cvlt_op_t op_type;
e3c68b
+    int32_t op_ret;
e3c68b
+    int32_t op_errno;
e3c68b
+    xlator_t *this;
e3c68b
+    sem_t sem;
e3c68b
+    archstore_info_t store_info;
e3c68b
+    archstore_fileinfo_t file_info;
e3c68b
+    cs_size_xattr_t szxattr;
e3c68b
+};
e3c68b
+typedef struct _cvlt_request cvlt_request_t;
e3c68b
+
e3c68b
+struct _archive {
e3c68b
+    gf_lock_t lock;                /* lock for controlling access   */
e3c68b
+    xlator_t *xl;                  /* xlator                        */
e3c68b
+    void *handle;                  /* handle returned from dlopen   */
e3c68b
+    int32_t nreqs;                 /* num requests active           */
e3c68b
+    struct mem_pool *req_pool;     /* pool for requests             */
e3c68b
+    struct iobuf_pool *iobuf_pool; /* iobuff pool                   */
e3c68b
+    archstore_desc_t descinfo;     /* Archive store descriptor info */
e3c68b
+    archstore_methods_t fops;      /* function pointers             */
e3c68b
+    char *product_id;
e3c68b
+    char *store_id;
e3c68b
+    char *trailer;
e3c68b
+};
e3c68b
+typedef struct _archive archive_t;
e3c68b
+
e3c68b
+void *
e3c68b
+cvlt_init(xlator_t *);
e3c68b
+
e3c68b
+int
e3c68b
+cvlt_reconfigure(xlator_t *, dict_t *);
e3c68b
+
e3c68b
+void
e3c68b
+cvlt_fini(void *);
e3c68b
+
e3c68b
+int
e3c68b
+cvlt_download(call_frame_t *, void *);
e3c68b
+
e3c68b
+int
e3c68b
+cvlt_read(call_frame_t *, void *);
e3c68b
+
e3c68b
+#endif
e3c68b
diff --git a/xlators/features/cloudsync/src/cloudsync.c b/xlators/features/cloudsync/src/cloudsync.c
e3c68b
index 2240fc3..8026b05 100644
e3c68b
--- a/xlators/features/cloudsync/src/cloudsync.c
e3c68b
+++ b/xlators/features/cloudsync/src/cloudsync.c
e3c68b
@@ -39,7 +39,11 @@ struct cs_plugin plugins[] = {
e3c68b
     {.name = "cloudsyncs3",
e3c68b
      .library = "cloudsyncs3.so",
e3c68b
      .description = "cloudsync s3 store."},
e3c68b
-
e3c68b
+#if defined(__linux__)
e3c68b
+    {.name = "cvlt",
e3c68b
+     .library = "cloudsynccvlt.so",
e3c68b
+     .description = "Commvault content store."},
e3c68b
+#endif
e3c68b
     {.name = NULL},
e3c68b
 };
e3c68b
 
e3c68b
diff --git a/xlators/mgmt/glusterd/src/glusterd-volume-set.c b/xlators/mgmt/glusterd/src/glusterd-volume-set.c
e3c68b
index 73abf37..7a83124 100644
e3c68b
--- a/xlators/mgmt/glusterd/src/glusterd-volume-set.c
e3c68b
+++ b/xlators/mgmt/glusterd/src/glusterd-volume-set.c
e3c68b
@@ -3724,6 +3724,14 @@ struct volopt_map_entry glusterd_volopt_map[] = {
e3c68b
     {.key = "features.cloudsync-remote-read",
e3c68b
      .voltype = "features/cloudsync",
e3c68b
      .value = "off",
e3c68b
-     .op_version = GD_OP_VERSION_6_0,
e3c68b
+     .op_version = GD_OP_VERSION_7_0,
e3c68b
+     .flags = VOLOPT_FLAG_CLIENT_OPT},
e3c68b
+    {.key = "features.cloudsync-store-id",
e3c68b
+     .voltype = "features/cloudsync",
e3c68b
+     .op_version = GD_OP_VERSION_7_0,
e3c68b
+     .flags = VOLOPT_FLAG_CLIENT_OPT},
e3c68b
+    {.key = "features.cloudsync-product-id",
e3c68b
+     .voltype = "features/cloudsync",
e3c68b
+     .op_version = GD_OP_VERSION_7_0,
e3c68b
      .flags = VOLOPT_FLAG_CLIENT_OPT},
e3c68b
     {.key = NULL}};
e3c68b
-- 
e3c68b
1.8.3.1
e3c68b