summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--xlators/features/changelog/src/changelog-helpers.c72
-rw-r--r--xlators/features/changelog/src/changelog-helpers.h3
-rw-r--r--xlators/features/changelog/src/changelog.c67
3 files changed, 135 insertions, 7 deletions
diff --git a/xlators/features/changelog/src/changelog-helpers.c b/xlators/features/changelog/src/changelog-helpers.c
index 9dccf45187c..3af2938190d 100644
--- a/xlators/features/changelog/src/changelog-helpers.c
+++ b/xlators/features/changelog/src/changelog-helpers.c
@@ -20,6 +20,7 @@
#include "syscall.h"
#include "changelog-helpers.h"
+#include "changelog-encoders.h"
#include "changelog-mem-types.h"
#include "changelog-encoders.h"
@@ -1337,3 +1338,74 @@ changelog_barrier_cleanup (xlator_t *this, changelog_priv_t *priv,
return;
}
/* End: Geo-Rep snapshot dependency changes */
+
+int32_t
+changelog_fill_entry_buf (call_frame_t *frame, xlator_t *this,
+ loc_t *loc, changelog_local_t **local)
+{
+ changelog_opt_t *co = NULL;
+ size_t xtra_len = 0;
+ char *dup_path = NULL;
+ char *bname = NULL;
+ inode_t *parent = NULL;
+
+ GF_ASSERT (this);
+
+ parent = inode_parent (loc->inode, 0, 0);
+ if (!parent) {
+ gf_log (this->name, GF_LOG_ERROR, "Parent inode not found"
+ " for gfid: %s", uuid_utoa (loc->inode->gfid));
+ goto err;
+ }
+
+ CHANGELOG_INIT_NOCHECK (this, *local, loc->inode, loc->inode->gfid, 5);
+ if (!(*local)) {
+ gf_log (this->name, GF_LOG_ERROR, "changelog local"
+ " initiatilization failed");
+ goto err;
+ }
+
+ co = changelog_get_usable_buffer (*local);
+ if (!co) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to get buffer");
+ goto err;
+ }
+
+ if (loc->inode->ia_type == IA_IFDIR) {
+ CHANGLOG_FILL_FOP_NUMBER (co, GF_FOP_MKDIR, fop_fn, xtra_len);
+ co++;
+ CHANGELOG_FILL_UINT32 (co, S_IFDIR|0755, number_fn, xtra_len);
+ co++;
+ } else {
+ CHANGLOG_FILL_FOP_NUMBER (co, GF_FOP_CREATE, fop_fn, xtra_len);
+ co++;
+ CHANGELOG_FILL_UINT32 (co, S_IFREG|0644, number_fn, xtra_len);
+ co++;
+ }
+
+ CHANGELOG_FILL_UINT32 (co, frame->root->uid, number_fn, xtra_len);
+ co++;
+
+ CHANGELOG_FILL_UINT32 (co, frame->root->gid, number_fn, xtra_len);
+ co++;
+
+ dup_path = gf_strdup (loc->path);
+ bname = basename (dup_path);
+
+ CHANGELOG_FILL_ENTRY (co, parent->gfid, bname, entry_fn, entry_free_fn,
+ xtra_len, err);
+ changelog_set_usable_record_and_length (*local, xtra_len, 5);
+
+ if (dup_path)
+ GF_FREE (dup_path);
+ if (parent)
+ inode_unref (parent);
+ return 0;
+
+err:
+ if (dup_path)
+ GF_FREE (dup_path);
+ if (parent)
+ inode_unref (parent);
+ return -1;
+}
diff --git a/xlators/features/changelog/src/changelog-helpers.h b/xlators/features/changelog/src/changelog-helpers.h
index d8f80465922..03a795369d1 100644
--- a/xlators/features/changelog/src/changelog-helpers.h
+++ b/xlators/features/changelog/src/changelog-helpers.h
@@ -456,6 +456,9 @@ void chlog_barrier_dequeue_all (xlator_t *this, struct list_head *queue);
call_stub_t *__chlog_barrier_dequeue (xlator_t *this, struct list_head *queue);
int __chlog_barrier_enable (xlator_t *this, changelog_priv_t *priv);
+int32_t
+changelog_fill_entry_buf (call_frame_t *frame, xlator_t *this,
+ loc_t *loc, changelog_local_t **local);
/* macros */
diff --git a/xlators/features/changelog/src/changelog.c b/xlators/features/changelog/src/changelog.c
index e047288d43d..4263a462ad7 100644
--- a/xlators/features/changelog/src/changelog.c
+++ b/xlators/features/changelog/src/changelog.c
@@ -1309,6 +1309,61 @@ changelog_setxattr_cbk (call_frame_t *frame,
return 0;
}
+/* changelog_handle_virtual_xattr:
+ * Handles virtual setxattr 'glusterfs.geo-rep.trigger-sync' on files.
+ * Following is the behaviour based on the value of xattr.
+ * 1: Captures only DATA entry in changelog.
+ * 2: Tries to captures both ENTRY and DATA entry in
+ * changelog. If failed to get pargfid, only DATA
+ * entry is captured.
+ * any other value: ENOTSUP is returned.
+ */
+static void
+changelog_handle_virtual_xattr (call_frame_t *frame, xlator_t *this,
+ loc_t *loc, dict_t *dict)
+{
+ changelog_priv_t *priv = NULL;
+ changelog_local_t *local = NULL;
+ int32_t value = 0;
+ int ret = 0;
+ int dict_ret = 0;
+ gf_boolean_t valid = _gf_false;
+
+ priv = this->private;
+ GF_ASSERT (priv);
+
+ dict_ret = dict_get_int32 (dict, GF_XATTR_TRIGGER_SYNC, &value);
+
+ if ((dict_ret == 0 && value == 1) && ((loc->inode->ia_type == IA_IFDIR)
+ || (loc->inode->ia_type == IA_IFREG)))
+ valid = _gf_true;
+
+ if (valid) {
+ ret = changelog_fill_entry_buf (frame, this, loc, &local);
+ if (ret) {
+ gf_log (this->name, GF_LOG_INFO, "Entry cannot be"
+ " captured for gfid: %s. Capturing DATA"
+ " entry.", uuid_utoa (loc->inode->gfid));
+ goto unwind;
+ }
+ changelog_update (this, priv, local, CHANGELOG_TYPE_ENTRY);
+
+ unwind:
+ /* Capture DATA only if it's a file. */
+ if (loc->inode->ia_type != IA_IFDIR)
+ changelog_update (this, priv, frame->local,
+ CHANGELOG_TYPE_DATA);
+ /* Assign local to prev_entry, so unwind will take
+ * care of cleanup. */
+ ((changelog_local_t *)(frame->local))->prev_entry = local;
+ CHANGELOG_STACK_UNWIND (setxattr, frame, 0, 0, NULL);
+ return;
+ } else {
+ CHANGELOG_STACK_UNWIND (setxattr, frame, -1, ENOTSUP, NULL);
+ return;
+ }
+}
+
int32_t
changelog_setxattr (call_frame_t *frame,
xlator_t *this, loc_t *loc,
@@ -1327,13 +1382,11 @@ changelog_setxattr (call_frame_t *frame,
loc->inode, loc->inode->gfid, 1);
/* On setting this virtual xattr on a file, an explicit data
- sync is triggered from geo-rep as DATA entry is recorded
- in changelog. */
- if (dict_get (dict, GF_XATTR_TRIGGER_SYNC)
- && loc->inode->ia_type != IA_IFDIR) {
- changelog_update (this, priv, frame->local,
- CHANGELOG_TYPE_DATA);
- CHANGELOG_STACK_UNWIND (setxattr, frame, 0, 0, xdata);
+ * sync is triggered from geo-rep as CREATE|DATA entry is
+ * recorded in changelog based on xattr value.
+ */
+ if (dict_get (dict, GF_XATTR_TRIGGER_SYNC)) {
+ changelog_handle_virtual_xattr (frame, this, loc, dict);
return 0;
}