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