diff options
Diffstat (limited to 'xlators/features/changelog')
-rw-r--r-- | xlators/features/changelog/src/changelog-encoders.c | 44 | ||||
-rw-r--r-- | xlators/features/changelog/src/changelog-encoders.h | 4 | ||||
-rw-r--r-- | xlators/features/changelog/src/changelog-helpers.c | 85 | ||||
-rw-r--r-- | xlators/features/changelog/src/changelog-helpers.h | 26 | ||||
-rw-r--r-- | xlators/features/changelog/src/changelog-misc.h | 2 | ||||
-rw-r--r-- | xlators/features/changelog/src/changelog.c | 32 |
6 files changed, 188 insertions, 5 deletions
diff --git a/xlators/features/changelog/src/changelog-encoders.c b/xlators/features/changelog/src/changelog-encoders.c index ea9db4061ca..ea395e11f90 100644 --- a/xlators/features/changelog/src/changelog-encoders.c +++ b/xlators/features/changelog/src/changelog-encoders.c @@ -39,6 +39,38 @@ entry_fn (void *data, char *buffer, gf_boolean_t encode) } size_t +del_entry_fn (void *data, char *buffer, gf_boolean_t encode) +{ + char *tmpbuf = NULL; + size_t bufsz = 0; + struct changelog_entry_fields *ce = NULL; + + ce = (struct changelog_entry_fields *) data; + + if (encode) { + tmpbuf = uuid_utoa (ce->cef_uuid); + CHANGELOG_FILL_BUFFER (buffer, bufsz, tmpbuf, strlen (tmpbuf)); + } else { + CHANGELOG_FILL_BUFFER (buffer, bufsz, + ce->cef_uuid, sizeof (uuid_t)); + } + + CHANGELOG_FILL_BUFFER (buffer, bufsz, "/", 1); + CHANGELOG_FILL_BUFFER (buffer, bufsz, + ce->cef_bname, strlen (ce->cef_bname)); + CHANGELOG_FILL_BUFFER (buffer, bufsz, "\0", 1); + + if (ce->cef_path[0] == '\0') { + CHANGELOG_FILL_BUFFER (buffer, bufsz, "\0", 1); + } else { + CHANGELOG_FILL_BUFFER (buffer, bufsz, + ce->cef_path, strlen (ce->cef_path)); + } + + return bufsz; +} + +size_t fop_fn (void *data, char *buffer, gf_boolean_t encode) { char buf[10] = {0,}; @@ -85,6 +117,18 @@ entry_free_fn (void *data) GF_FREE (co->co_entry.cef_bname); } +void +del_entry_free_fn (void *data) +{ + changelog_opt_t *co = data; + + if (!co) + return; + + GF_FREE (co->co_entry.cef_bname); + GF_FREE (co->co_entry.cef_path); +} + /** * try to write all data in one shot */ diff --git a/xlators/features/changelog/src/changelog-encoders.h b/xlators/features/changelog/src/changelog-encoders.h index c5dcc8a77d9..d6a50cc9ef7 100644 --- a/xlators/features/changelog/src/changelog-encoders.h +++ b/xlators/features/changelog/src/changelog-encoders.h @@ -33,11 +33,15 @@ size_t entry_fn (void *data, char *buffer, gf_boolean_t encode); size_t +del_entry_fn (void *data, char *buffer, gf_boolean_t encode); +size_t fop_fn (void *data, char *buffer, gf_boolean_t encode); size_t number_fn (void *data, char *buffer, gf_boolean_t encode); void entry_free_fn (void *data); +void +del_entry_free_fn (void *data); int changelog_encode_binary (xlator_t *, changelog_log_data_t *); int diff --git a/xlators/features/changelog/src/changelog-helpers.c b/xlators/features/changelog/src/changelog-helpers.c index 585214df635..8dae5efa454 100644 --- a/xlators/features/changelog/src/changelog-helpers.c +++ b/xlators/features/changelog/src/changelog-helpers.c @@ -1735,3 +1735,88 @@ err: inode_unref (parent); return -1; } + +/* + * resolve_pargfid_to_path: + * It converts given pargfid to path by doing recursive readlinks at the + * backend. If bname is given, it suffixes bname to pargfid to form the + * complete path else it doesn't. It allocates memory for the path and is + * caller's responsibility to free the same. If bname is NULL and pargfid + * is ROOT, then it returns "." + */ + +int +resolve_pargfid_to_path (xlator_t *this, uuid_t pargfid, + char **path, char *bname) +{ + char *linkname = NULL; + char *dir_handle = NULL; + char *pgfidstr = NULL; + char *saveptr = NULL; + ssize_t len = 0; + int ret = 0; + uuid_t tmp_gfid = {0, }; + changelog_priv_t *priv = NULL; + char gpath[PATH_MAX] = {0,}; + char result[PATH_MAX] = {0,}; + char *dir_name = NULL; + char pre_dir_name[PATH_MAX] = {0,}; + + GF_ASSERT (this); + priv = this->private; + GF_ASSERT (priv); + + if (!path || gf_uuid_is_null (pargfid)) { + ret = -1; + goto out; + } + + if (__is_root_gfid (pargfid)) { + if (bname) + *path = gf_strdup (bname); + else + *path = gf_strdup ("."); + return ret; + } + + dir_handle = alloca (PATH_MAX); + linkname = alloca (PATH_MAX); + (void) snprintf (gpath, PATH_MAX, "%s/.glusterfs/", + priv->changelog_brick); + + while (!(__is_root_gfid (pargfid))) { + snprintf (dir_handle, PATH_MAX, "%s/%02x/%02x/%s", gpath, + pargfid[0], pargfid[1], uuid_utoa (pargfid)); + + len = readlink (dir_handle, linkname, PATH_MAX); + if (len < 0) { + gf_log (this->name, GF_LOG_ERROR, "could not read the " + "link from the gfid handle %s (%s)", dir_handle, + strerror (errno)); + ret = -1; + goto out; + } + + linkname[len] = '\0'; + + pgfidstr = strtok_r (linkname + strlen("../../00/00/"), "/", + &saveptr); + dir_name = strtok_r (NULL, "/", &saveptr); + + strncpy (result, dir_name, PATH_MAX); + strncat (result, "/", 1); + strncat (result, pre_dir_name, PATH_MAX); + strncpy (pre_dir_name, result, PATH_MAX); + + gf_uuid_parse (pgfidstr, tmp_gfid); + gf_uuid_copy (pargfid, tmp_gfid); + } + + if (bname) + strncat (result, bname, PATH_MAX); + + *path = gf_strdup (result); + +out: + return ret; +} diff --git a/xlators/features/changelog/src/changelog-helpers.h b/xlators/features/changelog/src/changelog-helpers.h index b552c308e0f..ccfbf9113d8 100644 --- a/xlators/features/changelog/src/changelog-helpers.h +++ b/xlators/features/changelog/src/changelog-helpers.h @@ -306,6 +306,9 @@ struct changelog_priv { pthread_t *ev_dispatcher; changelog_clnt_t connections; + + /* glusterfind dependency to capture paths on deleted entries*/ + gf_boolean_t capture_del_path; }; struct changelog_local { @@ -349,6 +352,7 @@ typedef enum { struct changelog_entry_fields { uuid_t cef_uuid; char *cef_bname; + char *cef_path; }; typedef struct { @@ -497,6 +501,8 @@ changelog_dispatch_event (xlator_t *, changelog_priv_t *, changelog_event_t *); changelog_inode_ctx_t * __changelog_inode_ctx_get (xlator_t *, inode_t *, unsigned long **, unsigned long *, changelog_log_type); +int +resolve_pargfid_to_path (xlator_t *this, uuid_t gfid, char **path, char *bname); /* macros */ @@ -566,6 +572,26 @@ __changelog_inode_ctx_get (xlator_t *, inode_t *, unsigned long **, xlen += (UUID_CANONICAL_FORM_LEN + strlen (bname)); \ } while (0) +#define CHANGELOG_FILL_ENTRY_DIR_PATH(co, pargfid, bname, converter, \ + del_freefn, xlen, label, capture_del) \ + do { \ + co->co_convert = converter; \ + co->co_free = del_freefn; \ + co->co_type = CHANGELOG_OPT_REC_ENTRY; \ + gf_uuid_copy (co->co_entry.cef_uuid, pargfid); \ + co->co_entry.cef_bname = gf_strdup(bname); \ + if (!co->co_entry.cef_bname) \ + goto label; \ + xlen += (UUID_CANONICAL_FORM_LEN + strlen (bname)); \ + if (!capture_del || resolve_pargfid_to_path (this, pargfid, \ + &(co->co_entry.cef_path), co->co_entry.cef_bname)) { \ + co->co_entry.cef_path = gf_strdup ("\0"); \ + xlen += 1; \ + } else { \ + xlen += (strlen (co->co_entry.cef_path)); \ + } \ + } while (0) + #define CHANGELOG_INIT(this, local, inode, gfid, xrec) \ local = changelog_local_init (this, inode, gfid, xrec, _gf_false) diff --git a/xlators/features/changelog/src/changelog-misc.h b/xlators/features/changelog/src/changelog-misc.h index 0de0edd9516..acec6f675ac 100644 --- a/xlators/features/changelog/src/changelog-misc.h +++ b/xlators/features/changelog/src/changelog-misc.h @@ -23,7 +23,7 @@ #define HTIME_INITIAL_VALUE "0:0" #define CHANGELOG_VERSION_MAJOR 1 -#define CHANGELOG_VERSION_MINOR 1 +#define CHANGELOG_VERSION_MINOR 2 #define CHANGELOG_UNIX_SOCK DEFAULT_VAR_RUN_DIRECTORY"/changelog-%s.sock" #define CHANGELOG_TMP_UNIX_SOCK DEFAULT_VAR_RUN_DIRECTORY"/.%s%lu.sock" diff --git a/xlators/features/changelog/src/changelog.c b/xlators/features/changelog/src/changelog.c index 7429fc5e891..53c0cf85728 100644 --- a/xlators/features/changelog/src/changelog.c +++ b/xlators/features/changelog/src/changelog.c @@ -110,8 +110,15 @@ changelog_rmdir (call_frame_t *frame, xlator_t *this, CHANGLOG_FILL_FOP_NUMBER (co, frame->root->op, fop_fn, xtra_len); co++; - CHANGELOG_FILL_ENTRY (co, loc->pargfid, loc->name, - entry_fn, entry_free_fn, xtra_len, wind); + if (priv->capture_del_path) { + CHANGELOG_FILL_ENTRY_DIR_PATH (co, loc->pargfid, loc->name, + del_entry_fn, del_entry_free_fn, + xtra_len, wind, _gf_true); + } else { + CHANGELOG_FILL_ENTRY_DIR_PATH (co, loc->pargfid, loc->name, + del_entry_fn, del_entry_free_fn, + xtra_len, wind, _gf_false); + } changelog_set_usable_record_and_length (frame->local, xtra_len, 2); @@ -227,8 +234,15 @@ changelog_unlink (call_frame_t *frame, xlator_t *this, CHANGLOG_FILL_FOP_NUMBER (co, frame->root->op, fop_fn, xtra_len); co++; - CHANGELOG_FILL_ENTRY (co, loc->pargfid, loc->name, - entry_fn, entry_free_fn, xtra_len, wind); + if (priv->capture_del_path) { + CHANGELOG_FILL_ENTRY_DIR_PATH (co, loc->pargfid, loc->name, + del_entry_fn, del_entry_free_fn, + xtra_len, wind, _gf_true); + } else { + CHANGELOG_FILL_ENTRY_DIR_PATH (co, loc->pargfid, loc->name, + del_entry_fn, del_entry_free_fn, + xtra_len, wind, _gf_false); + } changelog_set_usable_record_and_length (frame->local, xtra_len, 2); @@ -2339,6 +2353,9 @@ reconfigure (xlator_t *this, dict_t *options) timeout, options, time, out); changelog_assign_barrier_timeout (priv, timeout); + GF_OPTION_RECONF ("capture-del-path", priv->capture_del_path, options, + bool, out); + if (active_now || active_earlier) { ret = changelog_fill_rollover_data (&cld, !active_now); if (ret) @@ -2443,6 +2460,8 @@ changelog_init_options (xlator_t *this, changelog_priv_t *priv) goto dealloc_2; GF_OPTION_INIT ("changelog", priv->active, bool, dealloc_2); + GF_OPTION_INIT ("capture-del-path", priv->capture_del_path, + bool, dealloc_2); GF_OPTION_INIT ("op-mode", tmp, str, dealloc_2); changelog_assign_opmode (priv, tmp); @@ -2719,6 +2738,11 @@ struct volume_options options[] = { "operations are no longer blocked and previously " "blocked fops are allowed to go through" }, + {.key = {"capture-del-path"}, + .type = GF_OPTION_TYPE_BOOL, + .default_value = "off", + .description = "enable/disable capturing paths of deleted entries" + }, {.key = {NULL} }, }; |