diff options
Diffstat (limited to '0154-cloudsync-cvlt-Cloudsync-plugin-for-commvault-store.patch')
-rw-r--r-- | 0154-cloudsync-cvlt-Cloudsync-plugin-for-commvault-store.patch | 1394 |
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 + |