summaryrefslogtreecommitdiffstats
path: root/xlators/features/changelog
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/features/changelog')
-rw-r--r--xlators/features/changelog/src/changelog-encoders.c44
-rw-r--r--xlators/features/changelog/src/changelog-encoders.h4
-rw-r--r--xlators/features/changelog/src/changelog-helpers.c85
-rw-r--r--xlators/features/changelog/src/changelog-helpers.h26
-rw-r--r--xlators/features/changelog/src/changelog-misc.h2
-rw-r--r--xlators/features/changelog/src/changelog.c32
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 a72ad25e4bc..0a29969194e 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 b7b1b95d3df..6658552ecf1 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}
},
};