diff options
Diffstat (limited to 'xlators/features/changelog/src')
-rw-r--r-- | xlators/features/changelog/src/changelog-helpers.c | 72 | ||||
-rw-r--r-- | xlators/features/changelog/src/changelog-helpers.h | 3 | ||||
-rw-r--r-- | xlators/features/changelog/src/changelog.c | 67 |
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; } |