You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1394 lines
42 KiB
1394 lines
42 KiB
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 |
|
|
|
|